

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/favicon.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="Blue~u~u~u">
  <meta name="author" content="Blue~u~u~u">
  <meta name="keywords" content="">
  <meta name="description" content="设计模式原则设计原则核心思想:  找出应用中可能需要变化之处，把他们独立出来，不要和那些不需要变化的代码放在一起。   针对接口编程，而不是针对实现编程。  为了交互对象之间的松耦合设计努力     12345678设计模式常见的七大原则：1)单一职责原则2)接口隔离原则3)依赖倒置原则4)里式替换原则5)开闭原则6)迪米特原则7)合成复用原则   代码重用性  可读性  可扩展性  可靠性  高">
<meta property="og:type" content="article">
<meta property="og:title" content="java设计模式">
<meta property="og:url" content="http://www.slx.blue/2021/12/03/javaDesignMode/index.html">
<meta property="og:site_name" content="Blue~u~u~u~u">
<meta property="og:description" content="设计模式原则设计原则核心思想:  找出应用中可能需要变化之处，把他们独立出来，不要和那些不需要变化的代码放在一起。   针对接口编程，而不是针对实现编程。  为了交互对象之间的松耦合设计努力     12345678设计模式常见的七大原则：1)单一职责原则2)接口隔离原则3)依赖倒置原则4)里式替换原则5)开闭原则6)迪米特原则7)合成复用原则   代码重用性  可读性  可扩展性  可靠性  高">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/TraditionalBuilder.jpg">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/improveBuilder-1637309987736.jpg">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/JDBCqiaojie.jpg">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/decorator.jpg">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/InputStream.jpg">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/composition.png">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/xiangyuan.jpg">
<meta property="og:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/command.png">
<meta property="article:published_time" content="2021-12-03T10:51:08.000Z">
<meta property="article:modified_time" content="2021-12-06T02:40:22.215Z">
<meta property="article:author" content="Blue~u~u~u">
<meta property="article:tag" content="设计模式">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://www.slx.blue/2021/12/03/javaDesignMode/TraditionalBuilder.jpg">
  
  <title>java设计模式 - Blue~u~u~u~u</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.slx.blue","root":"/","version":"1.8.12","typing":{"enable":true,"typeSpeed":180,"cursorChar":"_","loop":true},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname"}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>

<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css"/>
<script src="/live2d-widget/autoload.js"></script>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Blue~u~u</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/images/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="java设计模式">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-12-03 18:51" pubdate>
        2021年12月3日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      40k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      124 分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">java设计模式</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：6 个月前
                
              </p>
            
            <div class="markdown-body">
              <h1 id="设计模式原则"><a href="#设计模式原则" class="headerlink" title="设计模式原则"></a>设计模式原则</h1><p>设计原则核心思想:</p>
<ol>
<li><p>找出应用中可能需要变化之处，把他们独立出来，不要和那些不需要变化的代码放在一起。</p>
</li>
<li><p> 针对接口编程，而不是针对实现编程。</p>
</li>
<li><p>为了交互对象之间的松耦合设计努力  </p>
</li>
</ol>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs">设计模式常见的七大原则：<br>1)单一职责原则<br>2)接口隔离原则<br>3)依赖倒置原则<br>4)里式替换原则<br>5)开闭原则<br>6)迪米特原则<br>7)合成复用原则<br></code></pre></td></tr></table></figure>

<ol>
<li><p>代码重用性</p>
</li>
<li><p>可读性</p>
</li>
<li><p>可扩展性</p>
</li>
<li><p>可靠性</p>
</li>
<li><p>高内聚低耦合</p>
</li>
</ol>
<h2 id="单一隔离"><a href="#单一隔离" class="headerlink" title="单一隔离"></a>单一隔离</h2><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs">原则上 一个类应该尽量做一件事 一个类继承一个接口 <br>如果实现类两个职责 当职责一进行修改的时候 很可能回对职责二造成影响<br>但是一个类继承一个接口会导致开销过大<br>在接口方法比较少的情况下可以 通过向下兼容 实现方法的单一职责<br></code></pre></td></tr></table></figure>



<h2 id="接口隔离"><a href="#接口隔离" class="headerlink" title="接口隔离"></a>接口隔离</h2><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs">如果一个接口方法过多，实现该接口就会需要去实现很多不需要实现的方法。<br>这个时候我们就应该把接口进行拆分，去实现需要实现的接口即可。<br></code></pre></td></tr></table></figure>



<h2 id="依赖倒转-倒置"><a href="#依赖倒转-倒置" class="headerlink" title="依赖倒转(倒置)"></a>依赖倒转(倒置)</h2><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs actionscript">接口和抽象类的价值在于 设计<br>高层模块不应该依赖于底层模块<br>抽象不应该依赖细节，细节应该依赖抽象<br>面向接口编程<br>传递的三种方式<br><span class="hljs-number">1.</span>构造器传递<br><span class="hljs-number">2.</span><span class="hljs-keyword">set</span>接口传递<br><span class="hljs-number">3.</span>接口传递<br>使用接口或者抽象类的目的是制定好规范。而不涉及任何具体的操作，把展现细节的任务交给他们的实现类去完成<br>多了一个缓冲利于程序的扩展和优化<br><br></code></pre></td></tr></table></figure>



<h2 id="里式替换原则"><a href="#里式替换原则" class="headerlink" title="里式替换原则"></a>里式替换原则</h2><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs csharp">问题：在编程中如何正确的实现继承   尽量满足里式替换原则 <br>子类尽量不要重写父类的方法<br>做到透明使用 <br>如果子类想使用父类的方法 ，但是有可能会不小心重写了父类的方法 倒是一系列应用 带来了程序的入侵性<br>所以可以 子类和父类都继承一个新的<span class="hljs-keyword">base</span>类，<span class="hljs-keyword">base</span>类实现了更为基础的代码和方法<br>这样子类可以放心的重写方法<br>达到的效果是 所有应用基类的类应该尽量做到透明使用<br><br></code></pre></td></tr></table></figure>

<p>​    </p>
<h2 id="开闭原则"><a href="#开闭原则" class="headerlink" title="开闭原则"></a>开闭原则</h2><figure class="highlight fortran"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs fortran">开闭原则是编程中 最基础最重要的原则<br><br>一个软件实体类 模块和函数应该对外扩展开放(对提供方) 对修改关闭(对使用方)  用抽象构建，用实现扩展细节<br>当我们增加一个功能时候 应该增加代码而不是修改代码 尽量不去修改原有的代码 <br>当软件需要变化时 尽量通过扩展软件实体的行为来实现变化 而不是通过修改已有的代码来实现变化<br><br>编程中遵循其他原则以及使用设计模式的目的就是遵循开闭原则<br><br>改进思路分析 把创建的<span class="hljs-built_in">Shape</span>类做成抽象类或者接口，并提供一个抽象的draw方法或者接口，让子类去实现即可。<br>这样有新的图形种类时候 只需要让新的图形去继承<span class="hljs-built_in">Shape</span> 并且实现draw方法即可，这样使用方的代码就不需要修改<br><br>满足了开闭原则<br></code></pre></td></tr></table></figure>



<h2 id="迪米特法则"><a href="#迪米特法则" class="headerlink" title="迪米特法则"></a>迪米特法则</h2><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs">一个对象应该对其他的对象保持最少的了解<br>类与类之间的关系越密切，耦合度越大<br><br>一个类里面 除了传递参数依赖类 应该尽量避免出现其他的陌生类，降低耦合度 这样代码修改起来容易<br><br></code></pre></td></tr></table></figure>



<h2 id="合成服用原则"><a href="#合成服用原则" class="headerlink" title="合成服用原则"></a>合成服用原则</h2><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs dns">原则是尽量使用合成/聚合 而不是使用继承<br><br>B要想使用<span class="hljs-keyword">A</span>的方法，可以继承于<span class="hljs-keyword">A</span> 但是这样会导致关系太强 耦合度太高<br>组合： 让B 里面注入一个<span class="hljs-keyword">A</span> <br>聚合:  让B里面 set 一个<span class="hljs-keyword">A</span> 或者构造器<br>依赖： 在B里面把<span class="hljs-keyword">A</span>传进来 称之为B依赖<span class="hljs-keyword">A</span> 方法<br></code></pre></td></tr></table></figure>



<h1 id="设计模式类型"><a href="#设计模式类型" class="headerlink" title="设计模式类型"></a>设计模式类型</h1><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs">设计模式分为三种类型，共23种<br>1、创建型模式：单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式<br>2、适配器模式：桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式<br>3、行为型模式：模板方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、<br>备忘录模式、解释器模式、状态模式、策略模式、责任链模式<br></code></pre></td></tr></table></figure>

<h2 id="创建型模式"><a href="#创建型模式" class="headerlink" title="创建型模式"></a>创建型模式</h2><h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><h4 id="饿汉式-静态常量"><a href="#饿汉式-静态常量" class="headerlink" title="饿汉式(静态常量)"></a>饿汉式(静态常量)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span></span>&#123;<br>    <span class="hljs-comment">//构造器私有化 外部能new</span><br>    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span></span>&#123;<br>      <br>    &#125;<br>    <span class="hljs-comment">//本类内部创建对象实例</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">static</span> Singleton instance = <span class="hljs-keyword">new</span> Singleton();<br><br>	<span class="hljs-comment">//提供一个共有的静态方法 返回实例对象</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">return</span> instance;<br>    &#125;<br>&#125;<br><span class="hljs-comment">/*</span><br><span class="hljs-comment">写法较为简单，在类转载的时候就完成了实例化，避免了线程同步的问题。</span><br><span class="hljs-comment">缺点是在类装载的时候就完成实例化，没有达到懒加载的效果(Lazy Loading)。如果从始至终从未使用过这个实例，则会造成内存浪费，</span><br><span class="hljs-comment">这种基于类加载机制避免了多线程同步的问题，不过instance在类装载的时候就完成实例化，在单例模式中大多数都是调用getInstance方法，但是导致类装载的原因有很多种，因此不能确定有其他的方式导致类装载，这个时候初始化instance就没有达到懒加载的效果</span><br><span class="hljs-comment">这种单例模式可以用，有可能造成内存浪费</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<h4 id="饿汉式-静态代码块"><a href="#饿汉式-静态代码块" class="headerlink" title="饿汉式(静态代码块)"></a>饿汉式(静态代码块)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span></span>&#123;<br>    <span class="hljs-comment">//构造器私有化 外部能new</span><br>    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span></span>&#123;&#125;<br>    <span class="hljs-comment">//本类内部创建对象实例</span><br>    <span class="hljs-keyword">private</span>  <span class="hljs-keyword">static</span> Singleton instance ;<br>    <span class="hljs-keyword">static</span>&#123;<br>        instance = <span class="hljs-keyword">new</span> Singleton();<br>    &#125;<br><br>	<span class="hljs-comment">//提供一个共有的静态方法 返回实例对象</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">return</span> instance;<br>    &#125;<br>&#125;<br><span class="hljs-comment">//和静态常量类似，在静态代码块完成实例化。 优缺点也和饿汉式静态常量一样</span><br></code></pre></td></tr></table></figure>



<h4 id="懒汉式-线程不安全"><a href="#懒汉式-线程不安全" class="headerlink" title="懒汉式(线程不安全)"></a>懒汉式(线程不安全)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span></span>&#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;<br>    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span></span>&#123;&#125;<br><br>    <span class="hljs-comment">//提供一个静态方法，当使用这个方法的时候才实例化</span><br>    <span class="hljs-comment">//懒汉式(线程不安全)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>)&#123;<br>            instance = <span class="hljs-keyword">new</span> Singleton();<br>        &#125;<br>        <span class="hljs-keyword">return</span> instance;<br>    &#125;<br>&#125;<br><span class="hljs-comment">/*</span><br><span class="hljs-comment">小结：</span><br><span class="hljs-comment">1.起到了懒加载的效果，但是只能在多线程下才能使用</span><br><span class="hljs-comment">2.如果在多线程下 会导致线程不安全 一个线程进入if语句还没执行完 另一个线程也进来了 就会产生多个实例</span><br><span class="hljs-comment">3.在实际开发中 不要使用这种方式</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<h4 id="懒汉式-线程安全"><a href="#懒汉式-线程安全" class="headerlink" title="懒汉式(线程安全)"></a>懒汉式(线程安全)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span></span>&#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;<br>    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span></span>&#123;&#125;<br>    <span class="hljs-comment">//提供一个静态方法，加入同步处理的代码，解决了线程安全问题</span><br>    <span class="hljs-comment">//懒汉式(线程安全)</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>)&#123;<br>        	<span class="hljs-comment">//synchronized(Singleton.class)&#123; </span><br>            <span class="hljs-comment">//锁放在这里 并不能实现线程安全 因为线程进了if语句 迟早会执行 </span><br>                   instance = <span class="hljs-keyword">new</span> Singleton();<br>            <span class="hljs-comment">//&#125;    </span><br>        &#125;<br>        <span class="hljs-keyword">return</span> instance;<br>    &#125;<br>&#125;<br><span class="hljs-comment">/*</span><br><span class="hljs-comment">小结：</span><br><span class="hljs-comment">1.解决了线程不安全问题</span><br><span class="hljs-comment">2.效率太低了，每个线程想获得类的实例的时候 执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化就够了，后面想要获得该实例应该是直接return，方法进行同步效率太低</span><br><span class="hljs-comment">3.在实际开发中 不要使用这种方式</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<h4 id="双重检查-推荐"><a href="#双重检查-推荐" class="headerlink" title="双重检查(推荐)"></a>双重检查(推荐)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span></span>&#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">volatile</span> Singleton singleton;<br>    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span></span>&#123;&#125;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-comment">//双重检查</span><br>        <span class="hljs-comment">//提供一个静态的共有方法，加入双重检查代码，解决线程安全问题，同时解决懒加载问题</span><br>        <span class="hljs-keyword">if</span> (singleton == <span class="hljs-keyword">null</span>)&#123;<br>            <span class="hljs-keyword">synchronized</span> (Singleton.class)&#123;<br>                <span class="hljs-keyword">if</span> (singleton == <span class="hljs-keyword">null</span>)&#123;<br>                    singleton = <span class="hljs-keyword">new</span> Singleton();<br>                &#125;<br>            &#125;<br>        &#125;<br>        <span class="hljs-keyword">return</span> singleton;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">/*</span><br><span class="hljs-comment">小结：</span><br><span class="hljs-comment">1.双重检查 判断了两次singleton == null 就可以保证线程安全</span><br><span class="hljs-comment">2.实例化代码只用执行一次 后面再次访问 的时候 如果不为空 就可以直接返回实例化对象 避免了方法反复同步</span><br><span class="hljs-comment">3.线程安全：实现了懒加载，效率较高</span><br><span class="hljs-comment">在实际开发中 推荐使用这种单例设计模式</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<h4 id="静态内部类"><a href="#静态内部类" class="headerlink" title="静态内部类"></a>静态内部类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span></span>&#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">volatile</span> Singleton instance;<br>    <span class="hljs-comment">//　当一个共享变量被volatile修饰时，它会保证修改的值会立即被更新到主存，</span><br>    <span class="hljs-comment">//当有其他线程需要读取时，它会去内存中读取新值。 保证了 可见性。</span><br>    <span class="hljs-comment">// 满足并发编程安全的三大特性 原子性 可见性 有序性</span><br>    <span class="hljs-comment">//构造器私有化</span><br>    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span></span>&#123;&#125;<br>    <span class="hljs-comment">//写一个静态内部类，该类中有一个静态属性Singleton</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SingletonInstance</span></span>&#123;<br>        <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Singleton INSTANCE = <span class="hljs-keyword">new</span> Singleton();<br>    &#125;    <br>    <br>    <span class="hljs-comment">//提供一个静态方法，直接返回SingletonInstance.INSTANCE</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">return</span> SingletonInstance.INSTANCE;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">/*</span><br><span class="hljs-comment">小结:</span><br><span class="hljs-comment">1.这种方式采用的类装载机制来保证初始化实例只有一个线程</span><br><span class="hljs-comment">2.静态内部类方式在Singleton类被加载的时候并不会立即实例化，而是在需要实例化的时候，调用getInstacne方法，才会装在SingleInstance类，从而完成Singeleton的实例化</span><br><span class="hljs-comment">3.类的静态属性只会在第一次加载类的时候初始化，所以在这里，JVM帮助我们保证了线程的安全性，在类进行初始化的时候，别的线程是无法进入的。</span><br><span class="hljs-comment">4.避免了线程不安全，利用静态内部类特点实现了延迟加载，效率高。</span><br><span class="hljs-comment">在工作中推荐使用</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<h4 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">enum</span>  <span class="hljs-title">Singleton</span></span>&#123;<br>   INSTANCE;<br>   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sayOK</span><span class="hljs-params">()</span></span>&#123;<br>       System.out.println(<span class="hljs-string">&quot;ok~~~&quot;</span>);<br>   &#125;<br>&#125;<br><br><span class="hljs-comment">/*</span><br><span class="hljs-comment">小结</span><br><span class="hljs-comment">1.这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题，而且还能防止反序列化重新创建新的对象。</span><br><span class="hljs-comment">2.这种方式是Effective Jaca坐着Josh Bloch提倡的方式</span><br><span class="hljs-comment">推荐使用</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<p>单例模式有八种方式：</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs gcode">饿汉式<span class="hljs-comment">(静态常量实例化)</span><br>饿汉式<span class="hljs-comment">(静态代码块实例化)</span><br>懒汉式<span class="hljs-comment">(线程不安全)</span><br>懒汉式<span class="hljs-comment">(线程安全同步方法)</span><br>懒汉式<span class="hljs-comment">(同步代码块 ，写法错误)</span> 并不能实现线程安全<br>双重检查<br>静态内部类<br>枚举<br></code></pre></td></tr></table></figure>



<p>单例模式注意事项和细节说明：</p>
<p>1)单例模式保证了系统内存中 该类只存在一个对象，节省了系统资源，对于一些需要频繁创建销毁的对象，使用单例模式可提高系统的性能<br>2）当想实例化一个单例类的时候，必须要记住使用相应的获取对象的方法，而不是直接使用new<br>3）单例模式使用的场景：需要频繁的进行创建和销毁的对象、创建对象时耗时过多或者耗费资源过多（即重量级对象），但又经常用到的对象，工具类对象、频繁访问数据库或文件的对象（比如数据源、session工厂等）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java">如果确定实例一定会使用 饿汉式是可以使用的 只是有可能会造成内存浪费 <br>比如java的Runtime中就用了饿汉式 <br>推荐使用： 双重检查、静态内部类、枚举<br></code></pre></td></tr></table></figure>

<h3 id="工厂模式"><a href="#工厂模式" class="headerlink" title="工厂模式"></a>工厂模式</h3><h4 id="简单工厂模式"><a href="#简单工厂模式" class="headerlink" title="简单工厂模式"></a>简单工厂模式</h4><p>需求：一个披萨项目，要便于披萨种类的扩展，要便于维护</p>
<ol>
<li>披萨的种类有很多(比如<code>GreekPizz</code>、<code>Chjeesepizz</code>等)</li>
<li>披萨的制作有prepare，bake，cut，box</li>
<li>完成披萨店订购功能。</li>
</ol>
<h4 id="工厂方法模式"><a href="#工厂方法模式" class="headerlink" title="工厂方法模式"></a>工厂方法模式</h4><h4 id="抽象工厂模式"><a href="#抽象工厂模式" class="headerlink" title="抽象工厂模式"></a>抽象工厂模式</h4><ol>
<li>抽象工厂模式：定义了一个interface用于创建相关或有依赖关系的对象 cu答族，而无需指明具体的类</li>
<li>抽象工厂模式可以将简单工厂模式和工厂方法进行整合</li>
<li>从设计层面看，抽象工厂模式就是对简单工厂模式的改进或者说进一步的抽象</li>
<li>将工厂抽象成两橙，<code>AbsFactory</code>(抽象工厂)和具体实现的工厂子类，程序员可以根据创建对象类型使用对应的工厂子类。这样将单个简单地工厂变成了工厂cu答族，更利于代码的维护</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">定义一个抽象的工厂，然后定义实体工厂实现工厂方法。<br><br></code></pre></td></tr></table></figure>

<blockquote>
<p>Calendar中使用了工厂模式</p>
</blockquote>
<p>工厂模式小结</p>
<ol>
<li>工厂模式的意义：将实例化对象的代码提取出来，放到一个类中统一管理和维护，达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。</li>
<li>三种工厂模式（简单工厂模式，工厂方法模式，抽象工厂模式）</li>
<li>设计模式的依赖抽象原则<ul>
<li>创建对象实例中，不要直接new类，而是把这个new类的动作放在一个工厂的方法中，并返回。有的书上说不要直接持有具体类的应用。</li>
<li>不要让类继承具体类，而是继承抽象类或者是实现interface（接口）</li>
<li>不要覆盖基类中已经实现的方法</li>
</ul>
</li>
</ol>
<h3 id="原型模式"><a href="#原型模式" class="headerlink" title="原型模式"></a>原型模式</h3><h4 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h4><ul>
<li>现有一只羊，姓名为tom，年龄为1：颜色为白色，请编写程序创建和tom羊属性完全相同的10只羊</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//传统方式</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sheep</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;<br>    <span class="hljs-keyword">private</span> String color;<br>    <span class="hljs-comment">//生成构造和getset方法以及toString等等...</span><br>&#125;<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>     Sheep sheep = <span class="hljs-keyword">new</span> Sheep(<span class="hljs-string">&quot;tom&quot;</span>,<span class="hljs-number">1</span>,<span class="hljs-string">&quot;白色&quot;</span>);<br>     <span class="hljs-comment">//克隆十次...</span><br>     <span class="hljs-keyword">new</span> Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());<br> &#125;<br></code></pre></td></tr></table></figure>

<p>传统方式的优缺点</p>
<ol>
<li>有点是比较好理解，简单易操作</li>
<li>在创建新的对象时，总是需要重新获取原始对象的属性，如果创建的对象比较复杂，效率较低</li>
<li>总是需要重新初始化对象，而不是动态的获得对象运行时的状态，不够灵活</li>
</ol>
<p>思路：<code>java</code>中Object类是所有类的父类，Object提供了一个clone方法，可以将一个<code>java</code>对象复制一份，但是需要实现clone的<code>java</code>类需要实现一个接口<code>Clonealbe</code>，该接口表示该类能够复制且具有复制的能力=&gt;原型模式</p>
<h4 id="基本介绍"><a href="#基本介绍" class="headerlink" title="基本介绍"></a>基本介绍</h4><ol>
<li>原型模式(Prototype模式)是指：用原型实例指定创建对象的种类，并且通过拷贝这些原型，创建新的对象</li>
<li>原型模式是一种创建型设计模式，允许一个对象在创建另外一个可定制的对象，无需知道如何创建的细节</li>
<li>工作的原理：通过将一个原型对象传给那个要发动创建的对象，这个要发动创建的对象通过请求原型对象拷贝他们来实施创建，即对象.clone() </li>
<li>形象理解：猴子拔出猴毛变成其他猴子</li>
</ol>
<p>改进：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sheep</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Cloneable</span></span>&#123;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;<br>    <span class="hljs-keyword">private</span> String color;<br>     <span class="hljs-comment">//生成构造和getset方法以及toString等等...</span><br>	<span class="hljs-comment">//克隆该实例 使用默认的clone方法来完成</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">protected</span> Object <span class="hljs-title">clone</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> CloneNotSupportedException </span>&#123;<br>        Sheep sheep = <span class="hljs-keyword">null</span>;<br>        Sheep clone = (Sheep) <span class="hljs-keyword">super</span>.clone();<br>        <span class="hljs-keyword">return</span> clone;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span>  </span>&#123;<br>        Sheep sheep = <span class="hljs-keyword">new</span> Sheep(<span class="hljs-string">&quot;tom&quot;</span>,<span class="hljs-number">1</span>,<span class="hljs-string">&quot;包塞&quot;</span>);<br>        <span class="hljs-keyword">try</span> &#123;<br>            <span class="hljs-comment">//克隆十次</span><br>            Sheep clone1 = (Sheep) sheep.clone();<br>            Sheep clone2 = (Sheep) sheep.clone();<br>            <span class="hljs-comment">//....</span><br>        &#125; <span class="hljs-keyword">catch</span> (CloneNotSupportedException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>原型模式在Spring框架中源码分析</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testImport</span><span class="hljs-params">()</span></span>&#123;<br> Object bean1 = applicationContext.getBean(xxx);     <br>    Object bean2 = applicationContext.getBean(xxx);  <br>    <span class="hljs-comment">//如果是scope = prototype 多例 就用到了原型模式</span><br>    <span class="hljs-comment">//getbean每次都是通过clone生成的对象 </span><br>&#125;<br></code></pre></td></tr></table></figure>

<p>原型模式完成对象的创建，如果被克隆的对象中有对象属性，那么克隆的时候并不会被克隆</p>
<h4 id="深拷贝和浅拷贝"><a href="#深拷贝和浅拷贝" class="headerlink" title="深拷贝和浅拷贝"></a>深拷贝和浅拷贝</h4><p>浅拷贝：</p>
<ol>
<li>对于数据类型是基本类型的成员变量，浅拷贝会直接进行值传递，也就是将该属性复制一份给新的对象</li>
<li>对于数据类型是应用数据类型的成员变量，比如成员变量是某个数组，某个类的对象等，那么浅拷贝会进行引用传递，也就是只将该成员变量的引用值(内存地址)复制一份给新的对象。实际上两个对象都指向同一个实例，所以这种情况下 一个对象中修改该成员变量会影响到另一个对象的该成员变量值</li>
<li>比如默认开启的对象克隆就是浅拷贝</li>
<li><code> Sheep clone2 = (Sheep) sheep.clone();</code></li>
</ol>
<p>深拷贝：</p>
<ol>
<li>复制对象的<strong>所有</strong>基本数据类型的成员变量值 </li>
<li>为所有应用数据类型的成员变量<strong>申请存储空间</strong>，并复制每个应用数据类型成员变量所引用的对象，直到该对象可达的所有对象，<strong>也就是说，对象进行深拷贝要对整个对象(包括引用对象)进行拷贝</strong></li>
<li>深拷贝实现方式1：<strong>重写clone</strong>方法来实现深拷贝</li>
<li>深拷贝实现方式2：通过<strong>序列化</strong>实现深拷贝  </li>
</ol>
<h4 id="小案例"><a href="#小案例" class="headerlink" title="小案例"></a>小案例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//克隆引用对象</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeepCloneTarget</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span>,<span class="hljs-title">Cloneable</span> </span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">long</span> serialVersionUID = <span class="hljs-number">1L</span>;<br>    <span class="hljs-keyword">private</span> String cloneName;<br>    <span class="hljs-keyword">private</span> String cloneClass;<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DeepCloneTarget</span><span class="hljs-params">(String cloneName, String cloneClass)</span> </span>&#123;<br>        <span class="hljs-keyword">this</span>.cloneName = cloneName;<br>        <span class="hljs-keyword">this</span>.cloneClass = cloneClass;<br>    &#125;<br><br>    <span class="hljs-comment">//因为该类的属性都是string 所以直接用默认clone方式即可</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">protected</span> Object <span class="hljs-title">clone</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> CloneNotSupportedException </span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.clone();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//要克隆的对象 实现了两种克隆方式</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeepProtoType</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span>,<span class="hljs-title">Cloneable</span> </span>&#123;<br><br>    <span class="hljs-keyword">public</span> String name;<span class="hljs-comment">//String 属性</span><br>    <span class="hljs-keyword">public</span> DeepCloneTarget deepCloneTarget;<span class="hljs-comment">//引用类型 //属性是对象 默认克隆会浅拷贝</span><br>    <span class="hljs-comment">//深拷贝-1 使用重写clone方法</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">protected</span> Object <span class="hljs-title">clone</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> CloneNotSupportedException </span>&#123;<br>        Object deep = <span class="hljs-keyword">null</span>;<br>        <span class="hljs-comment">//这里完成对基本数据类型(属性)和字符串的clone</span><br>        deep = <span class="hljs-keyword">super</span>.clone();<br>        <span class="hljs-comment">//对引用类型的属性进行单独处理</span><br>        DeepProtoType deepProtoType = (DeepProtoType) deep;<br>        deepProtoType.deepCloneTarget = (DeepCloneTarget) deepCloneTarget.clone();<br>        <span class="hljs-keyword">return</span> deepProtoType;<br>    &#125;<br><br>    <span class="hljs-comment">//深拷贝2 使用对象的序列化实现(推荐)</span><br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">deepClone</span><span class="hljs-params">()</span></span>&#123;<br><br>        <span class="hljs-comment">//创建流对象</span><br>        ByteArrayOutputStream bos = <span class="hljs-keyword">null</span>;<br>        ObjectOutputStream oos = <span class="hljs-keyword">null</span>;<br>        ByteArrayInputStream bis = <span class="hljs-keyword">null</span>;<br>        ObjectInputStream ois = <span class="hljs-keyword">null</span>;<br>        <span class="hljs-keyword">try</span> &#123;<br>            bos = <span class="hljs-keyword">new</span> ByteArrayOutputStream();<br>            oos = <span class="hljs-keyword">new</span> ObjectOutputStream(bos);<br>            oos.writeObject(<span class="hljs-keyword">this</span>); <span class="hljs-comment">//当前这个对象以对象流的方式输出 序列化</span><br>            <span class="hljs-comment">//再反序列化 读出来 相当于存了值 成功克隆了一个新的对象</span><br>            bis = <span class="hljs-keyword">new</span> ByteArrayInputStream(bos.toByteArray());<br>            ois = <span class="hljs-keyword">new</span> ObjectInputStream(bis);<br>            DeepProtoType copy = (DeepProtoType) ois.readObject();<br>            <span class="hljs-keyword">return</span> copy;<br>        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>            e.printStackTrace();<br>            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;<br>        &#125;<span class="hljs-keyword">finally</span> &#123;<br>            <span class="hljs-keyword">try</span> &#123;<br>                bos.close();<br>                oos.close();<br>                bis.close();<br>                ois.close();<br>            &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>                e.printStackTrace();<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//测试</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> CloneNotSupportedException </span>&#123;<br>        DeepProtoType dp = <span class="hljs-keyword">new</span> DeepProtoType();<br>        dp.name = <span class="hljs-string">&quot;小水牛&quot;</span>;<br>        dp.deepCloneTarget = <span class="hljs-keyword">new</span> DeepCloneTarget(<span class="hljs-string">&quot;大水牛&quot;</span>, <span class="hljs-string">&quot;敲能喝&quot;</span>);<br>        <span class="hljs-comment">//方式一 完成深拷贝</span><br>       <span class="hljs-comment">/*</span><br><span class="hljs-comment">        DeepProtoType clone = (DeepProtoType) dp.clone();</span><br><span class="hljs-comment">        System.out.println(dp.hashCode());//460141958</span><br><span class="hljs-comment">        System.out.println(clone.hashCode());//1163157884</span><br><span class="hljs-comment">       */</span><br>       <span class="hljs-comment">//方式二 完成深拷贝</span><br>        DeepProtoType p = (DeepProtoType) dp.deepClone();<br>        System.out.println(<span class="hljs-string">&quot;克隆原型：&quot;</span>+dp.name + <span class="hljs-string">&quot;--&quot;</span> + dp.deepCloneTarget.hashCode());<br>        <span class="hljs-comment">//克隆原型：小水牛--325040804</span><br><br>        System.out.println(<span class="hljs-string">&quot;克隆的对象&quot;</span>+p.name + <span class="hljs-string">&quot;--&quot;</span> + p.deepCloneTarget.hashCode());<br>        <span class="hljs-comment">//克隆的对象小水牛--2065951873</span><br>    &#125;<br>&#125;<br><span class="hljs-comment">//推荐使用的是通过序列化实现深拷贝，这样无论原型如何修改都不会影响克隆 因为直接通过流来反序列化创建</span><br></code></pre></td></tr></table></figure>

<h4 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h4><ol>
<li>创建新的对象比较复杂时，可以利用原型模式简化对象的创建过程，同时也能够提高效率</li>
<li>不用重新初始化对象，而是动态的获得对象运行时的状态</li>
<li>如果原型对象发生变化（增加或减少属性），其他克隆对象也会发生相应的变化，无需修改代码</li>
<li>在实现深克隆的时候 可能需要比较复杂的代码</li>
<li>缺点：需要为每一个类配备一个克隆方法，这对全新的类来说不是很难，但是对已有的类来说进行改造的时候 需要修改它的源代码，违背了<code>OCP</code>（开闭原则）。</li>
</ol>
<h3 id="建造者模式"><a href="#建造者模式" class="headerlink" title="建造者模式"></a>建造者模式</h3><ol>
<li>需求：需要建房子 这一过程为打桩 砌墙 封顶</li>
<li>房子有各种各种的 比如普通房 高楼 别墅 各种房子的过程虽然一样 但是要求不要相同</li>
<li>编写程序完成需求</li>
</ol>
<h4 id="案例分析"><a href="#案例分析" class="headerlink" title="案例分析"></a>案例分析</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractHouse</span> </span>&#123;  <span class="hljs-comment">//抽象房子类</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildBasic</span><span class="hljs-params">()</span></span>;<span class="hljs-comment">// 打地基</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildWalls</span><span class="hljs-params">()</span></span>; <span class="hljs-comment">//砌墙</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">roofed</span><span class="hljs-params">()</span></span>;<span class="hljs-comment">//封顶</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">build</span><span class="hljs-params">()</span></span>&#123; <span class="hljs-comment">//造房子</span><br>        buildBasic();<br>        buildWalls();<br>        roofed();<br>    &#125;<br>&#125;<br><span class="hljs-comment">//普通房子类</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommonHouse</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractHouse</span> </span>&#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildBasic</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;给普通房子打地基&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildWalls</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;给普通房子砌墙&quot;</span>);<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">roofed</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;给普通房子封顶&quot;</span>);<br>    &#125;<br>&#125;<br><br><br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        CommonHouse commonHouse = <span class="hljs-keyword">new</span> CommonHouse();<br>        commonHouse.build();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/TraditionalBuilder.jpg" srcset="/img/loading.gif" lazyload alt="java"></p>
<ol>
<li><p>有点是比较好理解，简单易操作</p>
</li>
<li><p>设计的程序结构过于简单，没有设计缓存层对象，程序的扩展和维护不好,也就是说 这种设计方案把产品（房子）和创建产品的过程（建房子build方法）封装在一起 ，耦合性增强了</p>
</li>
<li><p>解决方案：将<strong>产品</strong>和<strong>产品建造过程</strong>解耦 =&gt; 建造者模式</p>
</li>
</ol>
<h4 id="基本介绍-1"><a href="#基本介绍-1" class="headerlink" title="基本介绍"></a>基本介绍</h4><ol>
<li>建造者模式(Builder Pattern)又叫生成器模式，是一种对象构建模式。它可以将复杂对象的建造过程抽象出来（抽象类别） 使这个抽象过程的不同方法可以构造出不同表现(属性)的对象。</li>
<li>建造者模式是一步一步创建一个复杂的对象 ，他允许用户指定复杂的类型就可以构建他们，用户不需要知道具体构建细节。</li>
</ol>
<h4 id="建造者模式的四个角色"><a href="#建造者模式的四个角色" class="headerlink" title="建造者模式的四个角色"></a>建造者模式的四个角色</h4><ol>
<li>Product(产品角色) ：一个具体的产品对象</li>
<li>Builder(抽象建造者)：创建一个Product对象的各个部件的接口/抽象类</li>
<li><code>ConcreteBuilder</code>(具体建造者)实现接口，构建和装配各个部件</li>
<li>Director(指挥者)：构建一个Builder接口的对象，它主要是用于创建一个复杂的对象。主要有两个作用，一是：隔离客户与对象产生的过程，二是：复杂控制产品对象的生产过程</li>
</ol>
<p>产品：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//产品</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">House</span> </span>&#123;<span class="hljs-comment">//对应产品</span><br>    <span class="hljs-keyword">private</span> String base;<br>    <span class="hljs-keyword">private</span> String wall;<br>    <span class="hljs-keyword">private</span> String roofed;<br><span class="hljs-comment">//对应getset方法</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p>抽象的建造者Builder:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HouseBuilder</span> </span>&#123;<br><br>    <span class="hljs-keyword">protected</span> House house = <span class="hljs-keyword">new</span> House(); <span class="hljs-comment">//组合一个产品</span><br>    <span class="hljs-comment">//将建造的流程写好,抽象方法</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildBasic</span><span class="hljs-params">()</span></span>;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildWalls</span><span class="hljs-params">()</span></span>;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">roofed</span><span class="hljs-params">()</span></span>;<br><br>    <span class="hljs-comment">//建造房子 建好后将房子返回</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> House <span class="hljs-title">BuildHouse</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">return</span> house;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>指挥者Director</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//指挥者 这里去指定制作流程 返回房子</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HouseDirector</span> </span>&#123;<br>    HouseBuilder houseBuilder = <span class="hljs-keyword">null</span>;<br>    <span class="hljs-comment">//1.构造器传入  依赖</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">HouseDirector</span><span class="hljs-params">(HouseBuilder houseBuilder)</span> </span>&#123;<br>        <span class="hljs-keyword">this</span>.houseBuilder = houseBuilder;<br>    &#125;<br>    <span class="hljs-comment">//2.通过set方法传入 聚合</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setHouseBuilder</span><span class="hljs-params">(HouseBuilder houseBuilder)</span> </span>&#123;<br>        <span class="hljs-keyword">this</span>.houseBuilder = houseBuilder;<br>    &#125;<br>    <span class="hljs-comment">//如何处理建房流程，交给指挥者</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> House <span class="hljs-title">constructorHouse</span><span class="hljs-params">()</span></span>&#123;<br>        houseBuilder.buildBasic();<br>        houseBuilder.buildWalls();<br>        houseBuilder.roofed();<br>        <span class="hljs-keyword">return</span> houseBuilder.BuildHouse();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>两个产品类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//普通房子</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommonHouse</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HouseBuilder</span></span>&#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildBasic</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;普通房子打地基五米&quot;</span>);<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildWalls</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;普通房子砌墙10cm&quot;</span>);<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">roofed</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;普通房子封顶&quot;</span>);<br>    &#125;<br>&#125;<br><span class="hljs-comment">//高楼</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HighBuilding</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HouseBuilder</span></span>&#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildBasic</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;高楼打地基50&quot;</span>);<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildWalls</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;高楼砌墙20cm&quot;</span>);<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">roofed</span><span class="hljs-params">()</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;高楼透明屋顶&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>实现：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        <span class="hljs-comment">//盖普通房子</span><br>        CommonHouse commonHouse = <span class="hljs-keyword">new</span> CommonHouse();<br>        <span class="hljs-comment">//准备创建房子的指挥者</span><br>        HouseDirector houseDirector = <span class="hljs-keyword">new</span> HouseDirector(commonHouse);<br>        <span class="hljs-comment">//完成盖房子，返回产品（房子）</span><br>        House house = houseDirector.constructorHouse();<br><br>        <span class="hljs-comment">//盖高楼</span><br>        HighBuilding highBuilding = <span class="hljs-keyword">new</span> HighBuilding();<br>        houseDirector.setHouseBuilder(highBuilding);<br>        House house1 = houseDirector.constructorHouse();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/improveBuilder-1637309987736.jpg" srcset="/img/loading.gif" lazyload alt="java"></p>
<p><code>JDK</code>中用到的建造者模式 <code>java.lang.StringBuilder</code></p>
<ul>
<li><code>Appendable</code>接口定义了多个append方法（抽象方法） ， 即<code>Appendable</code>为建造者，定义了抽象方法</li>
<li><code>AbstractStringBuilder</code>已经是建造者，只是不能实例化</li>
<li><code>StringBuilder</code>即充当了指挥者角色，同时同时充当了具体的建造者。建造方法的实现是由<code>AbstractStringBuilder</code>完成，而<code>StringBuilder</code>继承了<code>AbstractStringBuilder</code></li>
</ul>
<p><strong>建造者模式的注意事项和细节</strong></p>
<ol>
<li><p>客户端（使用程序）不必知道产品内部组成的细节，将产品本身与产品的创建过程解耦，使得相同的创建过程可以创建不同的产品对象。</p>
</li>
<li><p>建造者模式所创建的产品一般具有较多相同的共同点，其组成部分相似，如果产品之间的差异性很大，则不是和使用建造者模式，因此其使用范围收到一定的限制。</p>
</li>
<li><p>如果产品内部变化复杂，可能会导致需要定义很多具体建造者来实现这种变化，导致系统变得庞大，因此要考虑是否适合选择建造者模式。</p>
</li>
<li><p>每一个具体的建造者都相对独立，而与其他的具体建造者无关，因此可以很方便的替换具体建造者或者增加新的具体建造者，用户使用不同的建造者即可得到不同的产品对象。</p>
</li>
<li><p>可以更加精细的控制产品的建造过程，将复杂产品的创建步骤分解在不同的方法中，使得创建过程更加清晰，也更方便使用程序来控制创建流程。</p>
</li>
<li><p>增加新的具体创建者无需修改原油类库的代码，指挥者针对抽象建造者类变成，系统扩展方便，符合开闭原则。</p>
<blockquote>
<p><strong>抽象工厂模式和建造者模式</strong></p>
</blockquote>
<p>抽象工厂模式实现对产品家族的创建，一个产品家族是一系列产品，具有不同分类维度的产品组合，采用抽象工厂模式不需要关心构建过程，只关心什么产品由什么工厂生产。而建造者模式则是按照指定的蓝图构建产品，它的主要目的是通过组装零配件而生产一个新的产品。</p>
</li>
</ol>
<h2 id="结构型模式"><a href="#结构型模式" class="headerlink" title="结构型模式"></a>结构型模式</h2><h3 id="适配器模式"><a href="#适配器模式" class="headerlink" title="适配器模式"></a>适配器模式</h3><p>基本介绍</p>
<ol>
<li>适配器模式(<code>Adapter Pattern</code>)将某个类的接口转换成客户端期望的另一个接口表示，主要目的是兼容性，让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)</li>
<li>适配器模式属于结构型模式</li>
<li>主要分为三类:类适配器模式，对象适配器模式  ，接口适配器模式   </li>
</ol>
<p>工作原理</p>
<ul>
<li>适配器模式：将一个类的接口转换成另一种接口，让原本接口不兼容的类可以兼容</li>
<li>从用户的角度看不到适配者，是解耦的。</li>
<li>用户调用适配器转换出来的目标接口方法，适配器再调用被适配者的相关接口方法</li>
<li>用户收到反馈结果，只感觉是和目标接口交互</li>
</ul>
<h4 id="类适配器模式"><a href="#类适配器模式" class="headerlink" title="类适配器模式"></a>类适配器模式</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span>:被适配的类 src 提供方、</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Voltage220V</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">output220V</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">int</span> src = <span class="hljs-number">220</span>;<br>        System.out.println(<span class="hljs-string">&quot;电压=&quot;</span> + src + <span class="hljs-string">&quot;V&quot;</span>);<br>        <span class="hljs-keyword">return</span> src;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//充电接口</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Voltage5V</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">output5V</span><span class="hljs-params">()</span></span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span>:适配器类</span><br><span class="hljs-comment"> * 继承被适配的类 实现适配器类的接口</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VoltageAdapter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Voltage220V</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Voltage5V</span></span>&#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">output5V</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">int</span> srcV  = output220V();<br>        <span class="hljs-keyword">int</span> destV = srcV/<span class="hljs-number">44</span>;<br>        <span class="hljs-keyword">return</span> destV;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span>：手机 有充电方法 依赖了一个接口</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Phone</span> </span>&#123;<br>    <span class="hljs-comment">//充电方法</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">charging</span> <span class="hljs-params">(Voltage5V iVoltage)</span></span>&#123;<br>        <span class="hljs-keyword">if</span> (iVoltage.output5V() == <span class="hljs-number">5</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;电压为5V，可冲&quot;</span>);<br>        &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (iVoltage.output5V() &gt; <span class="hljs-number">5</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;电压大于5V 无法充电&quot;</span>);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;====类适配器模式&quot;</span>);<br>        Phone phone = <span class="hljs-keyword">new</span> Phone();<br>        phone.charging(<span class="hljs-keyword">new</span> VoltageAdapter());<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>类适配器模式注意事项和细节</p>
<ol>
<li>Java是单继承机制 ，所以类适配器需要继承<code>src</code>这一点算是一个缺点，因为这要求<code>dst</code>必须是接口，有一定的局限性</li>
<li><code>src</code>类的方法在Adapter中都会暴露出来，增加了使用成本</li>
<li>由于其继承了<code>src</code>类，所以它可以根据需求重写<code>src</code>类的方法，使得Adapter的灵活性增强了\</li>
</ol>
<h4 id="对象适配器"><a href="#对象适配器" class="headerlink" title="对象适配器"></a>对象适配器</h4><p>基本介绍</p>
<ol>
<li>基本思路和类的适配器相同，只是将Adapter类做修改，不是继承<code>src</code>类，而是持有<code>src</code>的类型，以解决兼容问题。即：持有<code>src</code>类，实现<code>dst</code>类接口，完成<code>src</code>-&gt;<code>dst</code>的适配。</li>
<li>根据“合成复用原则”，在系统中尽量使用关联关系来代替继承关系。</li>
<li>对象适配器模式是适配器模式常用的一种</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span>:被适配的类</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Voltage220V</span> </span>&#123;<br>    <span class="hljs-comment">//提供220电压</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">output220V</span><span class="hljs-params">()</span></span>&#123;<br>        <span class="hljs-keyword">int</span> src = <span class="hljs-number">220</span>;<br>        System.out.println(<span class="hljs-string">&quot;电压=&quot;</span> + src + <span class="hljs-string">&quot;V&quot;</span>);<br>        <span class="hljs-keyword">return</span> src;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//适配接口</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Voltage5V</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">output5V</span><span class="hljs-params">()</span></span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span>:适配器类</span><br><span class="hljs-comment"> * 继承被适配的类 实现适配器类的接口</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VoltageAdapter</span>  <span class="hljs-keyword">implements</span> <span class="hljs-title">Voltage5V</span> </span>&#123;<br>    <span class="hljs-keyword">private</span> Voltage220V voltage220;<br>    <span class="hljs-comment">//通过构造器 传入一个Voltage220V 实例</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">VoltageAdapter</span><span class="hljs-params">(Voltage220V voltage220)</span></span>&#123;<br>        <span class="hljs-keyword">this</span>.voltage220 = voltage220;<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">output5V</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">int</span> destV = <span class="hljs-number">0</span>;<br>        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">null</span> != voltage220)&#123;<br>            <span class="hljs-keyword">int</span> src = voltage220.output220V();<span class="hljs-comment">//获取220V电压</span><br>            System.out.println(<span class="hljs-string">&quot;适配器适配&quot;</span>);<br>            destV = src /<span class="hljs-number">44</span>;<br>            System.out.println(<span class="hljs-string">&quot;适配完成，输出的电压为&quot;</span> + destV);<br>        &#125;<br>        <span class="hljs-keyword">return</span> destV;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span>：手机 有充电方法 依赖了一个接口</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Phone</span> </span>&#123;<br>    <span class="hljs-comment">//充电方法</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">charging</span> <span class="hljs-params">(Voltage5V iVoltage)</span></span>&#123;<br>        <span class="hljs-keyword">if</span> (iVoltage.output5V() == <span class="hljs-number">5</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;电压为5V，可冲&quot;</span>);<br>        &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (iVoltage.output5V() &gt; <span class="hljs-number">5</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;电压大于5V 无法充电&quot;</span>);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;====对象适配器模式&quot;</span>);<br>        Phone phone = <span class="hljs-keyword">new</span> Phone();<br>        phone.charging(<span class="hljs-keyword">new</span> VoltageAdapter(<span class="hljs-keyword">new</span> Voltage220V() ));<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>对象适配器模式注意事项和细节</p>
<ol>
<li>对象适配器和类适配器算是同一种思想，只不过是实现方式不同。根据合成服用原则，使用组合替代继承，所以他解决了适配器必须继承<code>src</code>的局限性问题，也不再要修<code>dst</code>必须是接口。</li>
<li>使用成本更低，更灵活</li>
</ol>
<h4 id="接口适配器模式"><a href="#接口适配器模式" class="headerlink" title="接口适配器模式"></a>接口适配器模式</h4><p>基本介绍</p>
<ol>
<li>一些书籍称为：适配器模式（Default Adapter Pattern）或缺省适配器模式。</li>
<li>当不需要全部实现接口提供的方法时，可以设计一个抽象类实现接口，并为该接口中每一个方法提供一个<strong>默认实现（空方法）</strong>，那么该抽象类的子类可有选择的覆盖父类的某些方法实现需求。</li>
<li>适用于一个接口不想使用其所有的方法的情况。</li>
</ol>
<h4 id="源码分析"><a href="#源码分析" class="headerlink" title="源码分析"></a>源码分析</h4><ul>
<li><code>SpringMVC</code>中的<code>HandlerAdapter</code>就使用到了适配器模式 <strong>很牛逼，但是现在看不懂，记得回来看~</strong></li>
</ul>
<h4 id="小结-1"><a href="#小结-1" class="headerlink" title="小结"></a>小结</h4><ol>
<li>三种命名方式，是根据<code>src</code>以怎样的形式给到Adapter(在<code>Adapte</code>里的形式)来命名的。</li>
<li>三种适配器<ul>
<li>类适配器：以类给到，在Adapter里，就是将<code>src</code>当做类继承</li>
<li>对象适配器：以对象给到，在Adapter里，将<code>src</code>作为一个对象持有</li>
<li>接口适配器：以接口给到，在Adapter里，将<code>src</code>作为一个接口，实现</li>
</ul>
</li>
<li>Adapter模式最大的作用还是将原本不兼容的接口融合在一起工作。</li>
<li>实际开发中 实现不拘泥于这三种经典形式</li>
</ol>
<h3 id="桥接模式"><a href="#桥接模式" class="headerlink" title="桥接模式"></a>桥接模式</h3><p>问题分析：类爆炸问题。</p>
<h4 id="基本介绍-2"><a href="#基本介绍-2" class="headerlink" title="基本介绍"></a>基本介绍</h4><ul>
<li>桥接模式(Bridge)：将实现与抽象类在两个不同的类层次中，使两个层次可以独立改变</li>
<li>Bridge基于类的最小设计原则，通过使用继承，聚合，封装等不同方式来让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)和实现(Implementation)分离开，从而可以保证各个部分的独立性以及对他们的功能扩展</li>
</ul>
<p>代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//接口</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Brand</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">open</span><span class="hljs-params">()</span></span>;<br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">close</span><span class="hljs-params">()</span></span>;<br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">call</span><span class="hljs-params">()</span></span>;<br>&#125;<br><span class="hljs-comment">//Vivo实现类</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Vivo</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Brand</span> </span>&#123;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">open</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; Vivo手机开机 &quot;</span>);<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">close</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; Vivo手机关机 &quot;</span>);<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">call</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; Vivo手机打电话 &quot;</span>);<br>	&#125;<br>&#125;<br><span class="hljs-comment">//XiaoMi实现类</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XiaoMi</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Brand</span> </span>&#123;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">open</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 小米手机开机 &quot;</span>);<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">close</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 小米手机关机 &quot;</span>);<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">call</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 小米手机打电话 &quot;</span>);<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//抽象成 桥</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Phone</span> </span>&#123;<br>	<span class="hljs-comment">//组合品牌</span><br>	<span class="hljs-keyword">private</span> Brand brand;<br>	<span class="hljs-comment">//构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Phone</span><span class="hljs-params">(Brand brand)</span> </span>&#123;<span class="hljs-keyword">this</span>.brand = brand;&#125;<br><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">open</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">this</span>.brand.open();<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">close</span><span class="hljs-params">()</span> </span>&#123;<br>		brand.close();<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">call</span><span class="hljs-params">()</span> </span>&#123;<br>		brand.call();<br>	&#125;<br>&#125;<br><span class="hljs-comment">//两个抽象子类</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UpRightPhone</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Phone</span> </span>&#123;<br>	<span class="hljs-comment">//构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UpRightPhone</span><span class="hljs-params">(Brand brand)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(brand);<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">open</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>.open();<br>		System.out.println(<span class="hljs-string">&quot; 直立样式手机 &quot;</span>);<br>	&#125;<br><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">close</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>.close();<br>		System.out.println(<span class="hljs-string">&quot; 直立样式手机 &quot;</span>);<br>	&#125;<br><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">call</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>.call();<br>		System.out.println(<span class="hljs-string">&quot; 直立样式手机 &quot;</span>);<br>	&#125;<br>&#125;<br><span class="hljs-comment">//折叠式手机类，继承 抽象类 Phone</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FoldedPhone</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Phone</span> </span>&#123;<br>	<span class="hljs-comment">//构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">FoldedPhone</span><span class="hljs-params">(Brand brand)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(brand);<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">open</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>.open();<br>		System.out.println(<span class="hljs-string">&quot; 折叠样式手机 &quot;</span>);<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">close</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>.close();<br>		System.out.println(<span class="hljs-string">&quot; 折叠样式手机 &quot;</span>);<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">call</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>.call();<br>		System.out.println(<span class="hljs-string">&quot; 折叠样式手机 &quot;</span>);<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//客户端实现方式</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		<span class="hljs-comment">//获取折叠式手机 (样式 + 品牌 )</span><br>		Phone phone1 = <span class="hljs-keyword">new</span> FoldedPhone(<span class="hljs-keyword">new</span> XiaoMi());<br>		phone1.open();<br>		phone1.call();<br>		phone1.close();<br><br>		Phone phone2 = <span class="hljs-keyword">new</span> FoldedPhone(<span class="hljs-keyword">new</span> Vivo());<br>		phone2.open();<br>		phone2.call();<br>		phone2.close();<br><br>		UpRightPhone phone3 = <span class="hljs-keyword">new</span> UpRightPhone(<span class="hljs-keyword">new</span> XiaoMi());<br>		phone3.open();<br>		phone3.call();<br>		phone3.close();<br><br>		UpRightPhone phone4 = <span class="hljs-keyword">new</span> UpRightPhone(<span class="hljs-keyword">new</span> Vivo());<br>		phone4.open();<br>		phone4.call();<br>		phone4.close();<br>	&#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>



<h4 id="源码分析-1"><a href="#源码分析-1" class="headerlink" title="源码分析"></a>源码分析</h4><ol>
<li><code>JDBC</code>的Driver接口，从桥接模式来看，Driver就是一个接口，下面可以有<code>Mysql</code>的Driver，也可以有<code>Orical</code>的Driver，这些就可以当做实现接口类</li>
</ol>
<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/JDBCqiaojie.jpg" srcset="/img/loading.gif" lazyload alt="java"></p>
<h4 id="小结-2"><a href="#小结-2" class="headerlink" title="小结"></a>小结</h4><ol>
<li>实现了抽象和实现类的分离，极大地提升了系统的灵活性，让抽象类和实现类部分独立开，有助于系统实现分层设计，从而产生更好的结构化系统。</li>
<li>对于系统的高层部分，只需要知道抽象部分和实现部分的接口即可，其他的部分有具体业务来完成。</li>
<li>桥接模式替代了多层继承方案，可以减少子类的个数，降低系统的管理和维护成本。</li>
<li>桥接模式的引入增加了系统的理解和设计难度，由于聚和关联关系建立在抽象层，要求开发者针对抽象进行设计和编程。</li>
<li>桥接模式要求正确识别出系统两个独立变化的维度，因此适用范围有一定的局限性。</li>
<li>常见的应用场景:<ul>
<li><code>JDBC</code>驱动系统</li>
<li>银行转账系统<ul>
<li>转账分类：网上转账，柜台转账，ATM转账</li>
<li>转账用户类型：普通用户，银卡用户，金卡用户…</li>
</ul>
</li>
<li>消息管理<ul>
<li>消息类型：即使消息，延时消息..</li>
<li>消息分类：短信，<code>QQ</code>，微信..</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="装饰者模式"><a href="#装饰者模式" class="headerlink" title="装饰者模式"></a>装饰者模式</h3><blockquote>
<p><strong>定义</strong>：<strong>动态的将新功能附加到对象上</strong>，在对象功能扩展方面，比继承更有弹性，也体现了开闭原则(<code>OCP</code>)</p>
</blockquote>
<h4 id="案例分析-1"><a href="#案例分析-1" class="headerlink" title="案例分析"></a>案例分析</h4><ul>
<li>星巴克咖啡订单项目(咖啡馆)</li>
<li>咖啡种类/单品咖啡：咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、<code>ShortBlack</code>、<code>LongBlack</code>(美式咖啡)、Decaf(无因咖啡)</li>
<li>调料:Milk、Soy(豆浆)、Chocolate</li>
<li>要求在扩展新的咖啡种类时，具有良好的扩展性、改动方便、维护方便</li>
<li>使用<code>OO</code>的来计算不同种类咖啡的费用:客户可以点单品咖啡，也可以单品咖啡+调料组合。</li>
</ul>
<p>分析，一份单品咖啡可能有多份调料，而且单品咖啡和调料应该易于扩展，符合开闭原则。所以不能把单品咖啡和调料融合在一起，应该把咖啡当做<strong>被装饰者</strong>，调料当成<strong>装饰者</strong>，实现调料的具体子类为修饰着。图解图下</p>
<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/decorator.jpg" srcset="/img/loading.gif" lazyload alt="java"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//总抽象类Drink 被装饰者</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Drink</span> </span>&#123;<br>	<span class="hljs-keyword">public</span> String des; <span class="hljs-comment">// 描述</span><br>	<span class="hljs-keyword">private</span> <span class="hljs-keyword">float</span> price = <span class="hljs-number">0.0f</span>;<br>	<span class="hljs-comment">//...实现get 和 set方法</span><br>    <br>	<span class="hljs-comment">//计算费用的抽象方法</span><br>	<span class="hljs-comment">//子类来实现</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">float</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span></span>;<br>&#125;<br><br><span class="hljs-comment">//咖啡类 作为缓存层  旗下是单体咖啡实类</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Coffee</span>  <span class="hljs-keyword">extends</span> <span class="hljs-title">Drink</span> </span>&#123;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">float</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getPrice();<br>	&#125;<br>&#125;<br><span class="hljs-comment">//两种咖啡种类</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeCaf</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Coffee</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DeCaf</span><span class="hljs-params">()</span> </span>&#123;<br>		setDes(<span class="hljs-string">&quot; 无因咖啡 &quot;</span>); <span class="hljs-comment">//介绍</span><br>		setPrice(<span class="hljs-number">1.0f</span>);		<span class="hljs-comment">//咖啡价格</span><br>	&#125;<br>&#125;<br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Espresso</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Coffee</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Espresso</span><span class="hljs-params">()</span> </span>&#123;<br>		setDes(<span class="hljs-string">&quot; 意大利咖啡 &quot;</span>);<br>		setPrice(<span class="hljs-number">6.0f</span>);<br>	&#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//Decorator装饰者</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Decorator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Drink</span> </span>&#123;<br>	<span class="hljs-keyword">private</span> Drink obj; <span class="hljs-comment">//被装饰者</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Decorator</span><span class="hljs-params">(Drink obj)</span> </span>&#123; <span class="hljs-comment">//组合被装饰者</span><br>		<span class="hljs-keyword">this</span>.obj = obj;<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">float</span> <span class="hljs-title">cost</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">// getPrice 自己价格</span><br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getPrice() + obj.cost();<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDes</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">// obj.getDes() 输出被装饰者的信息</span><br>		<span class="hljs-keyword">return</span> des + <span class="hljs-string">&quot; &quot;</span> + getPrice() + <span class="hljs-string">&quot; &amp;&amp; &quot;</span> + obj.getDes();<br>	&#125;<br>&#125;<br><span class="hljs-comment">//具体的Decorator， 这里就是调味品</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Milk</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Decorator</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Milk</span><span class="hljs-params">(Drink obj)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(obj);<br>		setDes(<span class="hljs-string">&quot; 牛奶 &quot;</span>);<br>		setPrice(<span class="hljs-number">2.0f</span>); <br>	&#125;<br>&#125;<br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Soy</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Decorator</span></span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Soy</span><span class="hljs-params">(Drink obj)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(obj);<br>		setDes(<span class="hljs-string">&quot; 豆浆  &quot;</span>);<br>		setPrice(<span class="hljs-number">1.5f</span>);<br>	&#125;<br>&#125;<br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Chocolate</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Decorator</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Chocolate</span><span class="hljs-params">(Drink obj)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(obj);<br>		setDes(<span class="hljs-string">&quot; 巧克力 &quot;</span>);<br>		setPrice(<span class="hljs-number">3.0f</span>); <span class="hljs-comment">// 调味品 的价格</span><br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//具体实现代码</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CoffeeBar</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		<span class="hljs-comment">// 装饰者模式下的订单：2份巧克力+一份牛奶的LongBlack</span><br><br>		<span class="hljs-comment">// 1. 点一份 LongBlack</span><br>		Drink order = <span class="hljs-keyword">new</span> LongBlack();<br>		System.out.println(<span class="hljs-string">&quot;费用1=&quot;</span> + order.cost());<br>		System.out.println(<span class="hljs-string">&quot;描述=&quot;</span> + order.getDes());<br><br>		<span class="hljs-comment">// 2. order 加入一份牛奶</span><br>		order = <span class="hljs-keyword">new</span> Milk(order);<br>		System.out.println(<span class="hljs-string">&quot;order 加入一份牛奶 费用 =&quot;</span> + order.cost());<br>		System.out.println(<span class="hljs-string">&quot;order 加入一份牛奶 描述 = &quot;</span> + order.getDes());<br><br>		<span class="hljs-comment">// 3. order 加入一份巧克力</span><br>		order = <span class="hljs-keyword">new</span> Chocolate(order);<br><br>		System.out.println(<span class="hljs-string">&quot;order 加入一份牛奶 加入一份巧克力  费用 =&quot;</span> + order.cost());<br>		System.out.println(<span class="hljs-string">&quot;order 加入一份牛奶 加入一份巧克力 描述 = &quot;</span> + order.getDes());<br><br>		<span class="hljs-comment">// 3. order 加入一份巧克力</span><br>		order = <span class="hljs-keyword">new</span> Chocolate(order);<br><br>		System.out.println(<span class="hljs-string">&quot;order 加入一份牛奶 加入2份巧克力   费用 =&quot;</span> + order.cost());<br>		System.out.println(<span class="hljs-string">&quot;order 加入一份牛奶 加入2份巧克力 描述 = &quot;</span> + order.getDes());<br>		System.out.println(<span class="hljs-string">&quot;===========================&quot;</span>);<br>		<br>		Drink order2 = <span class="hljs-keyword">new</span> DeCaf();<br>		<br>		System.out.println(<span class="hljs-string">&quot;order2 无因咖啡  费用 =&quot;</span> + order2.cost());<br>		System.out.println(<span class="hljs-string">&quot;order2 无因咖啡 描述 = &quot;</span> + order2.getDes());<br>		<br>		order2 = <span class="hljs-keyword">new</span> Milk(order2);<br>		<br>		System.out.println(<span class="hljs-string">&quot;order2 无因咖啡 加入一份牛奶  费用 =&quot;</span> + order2.cost());<br>		System.out.println(<span class="hljs-string">&quot;order2 无因咖啡 加入一份牛奶 描述 = &quot;</span> + order2.getDes());<br>	&#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>



<h4 id="源码分析-2"><a href="#源码分析-2" class="headerlink" title="源码分析"></a>源码分析</h4><blockquote>
<p>Java的IO结构，<code>FilterInputStream</code>就是一个<strong>装饰者</strong></p>
</blockquote>
<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/InputStream.jpg" srcset="/img/loading.gif" lazyload alt="java"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DecoratorToJDKIO</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>&#123;<br>        <span class="hljs-comment">/*说明</span><br><span class="hljs-comment">            1. InputStream是抽象类,类似我们前面讲的 Drink</span><br><span class="hljs-comment">            2.FileInputStream是 InputStream子类，类似我们前面的 DeCaf, LongBlack</span><br><span class="hljs-comment">            3.FilterInputStream是 InputStream子类:类似我们前面的Decorator修饰者</span><br><span class="hljs-comment">            4. DatalnputStream是 FilterInputStream子类，具体的修饰者，类似前面的 Milk, Soy 等</span><br><span class="hljs-comment">            5.FilterInputStream类有protected volatile InputStream in;即含被装饰者</span><br><span class="hljs-comment">            6.分析得出在jdk 的io体系中，就是使用装饰者模式</span><br><span class="hljs-comment">         */</span><br>        DataInputStream dis = <span class="hljs-keyword">new</span> DataInputStream(<span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;/&quot;</span>));<br>        System.out.println(dis.read());<br>        dis.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="组合模式"><a href="#组合模式" class="headerlink" title="组合模式"></a>组合模式</h3><h4 id="案例分析："><a href="#案例分析：" class="headerlink" title="案例分析："></a>案例分析：</h4><p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/composition.png" srcset="/img/loading.gif" lazyload alt="java"></p>
<p>传统方案解决问题分析</p>
<ul>
<li>将学院看做了学校的子类，将专业看做了学院的子类，相当于从组织大小进行分成</li>
<li>但是这样不能很好的实现管理操作，比如增删改查。</li>
<li>解决方案，把学校，学院，专业当做组织结构，她们之间没有继承关系，而是一个树形结构，可以更好的实现管理操作，=&gt; 组合模式</li>
</ul>
<h4 id="基本介绍-3"><a href="#基本介绍-3" class="headerlink" title="基本介绍"></a>基本介绍</h4><ol>
<li>组合模式(Composite Patterm）)，又叫部分整体模式，它创建了对象组的树形结构，将对象组合成树状结构以表示“整体-部分”的层次关系。</li>
<li>组合模式依据树形结构来组合对象，用来表示部分以及整体层次。</li>
<li>组合模式使得用户对单个对象和组合对象的访问具有一致性，即:组合能让客户以一致的方式处理个别对象以及组合对象</li>
</ol>
<h4 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrganizationComponent</span> </span>&#123;<br>	<span class="hljs-keyword">private</span> String name; <span class="hljs-comment">// 名字</span><br>	<span class="hljs-keyword">private</span> String des; <span class="hljs-comment">// 说明</span><br>	<br>	<span class="hljs-function"><span class="hljs-keyword">protected</span>  <span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(OrganizationComponent organizationComponent)</span> </span>&#123;<br>		<span class="hljs-comment">//默认实现</span><br>		<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnsupportedOperationException();<span class="hljs-comment">//不支持操作异常</span><br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">protected</span>  <span class="hljs-keyword">void</span> <span class="hljs-title">remove</span><span class="hljs-params">(OrganizationComponent organizationComponent)</span> </span>&#123;<br>		<span class="hljs-comment">//默认实现</span><br>		<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnsupportedOperationException();<br>	&#125;<br>	<span class="hljs-comment">//构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">OrganizationComponent</span><span class="hljs-params">(String name, String des)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>();<br>		<span class="hljs-keyword">this</span>.name = name;<br>		<span class="hljs-keyword">this</span>.des = des;<br>	&#125;<br>	<span class="hljs-comment">//实现getset方法。。。。</span><br>	<br>	<span class="hljs-comment">//方法print, 做成抽象的, 子类都需要实现</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span></span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//College</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">College</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">OrganizationComponent</span> </span>&#123;<br><br>	<span class="hljs-comment">//List 中 存放的Department</span><br>	List&lt;OrganizationComponent&gt; organizationComponents = <span class="hljs-keyword">new</span> ArrayList&lt;OrganizationComponent&gt;();<br><br>	<span class="hljs-comment">// 构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">College</span><span class="hljs-params">(String name, String des)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(name, des);<br>	&#125;<br>	<span class="hljs-comment">// 重写add</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(OrganizationComponent organizationComponent)</span> </span>&#123;<br>		<span class="hljs-comment">//  将来实际业务中，Colleage 的 add 和  University add 不一定完全一样</span><br>		organizationComponents.add(organizationComponent);<br>	&#125;<br>	<span class="hljs-comment">// 重写remove</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">remove</span><span class="hljs-params">(OrganizationComponent organizationComponent)</span> </span>&#123;<br>		organizationComponents.remove(organizationComponent);<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getName();<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDes</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getDes();<br>	&#125;<br>	<span class="hljs-comment">// print方法，就是输出University 包含的学院</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;--------------&quot;</span> + getName() + <span class="hljs-string">&quot;--------------&quot;</span>);<br>		<span class="hljs-comment">//遍历 organizationComponents </span><br>		<span class="hljs-keyword">for</span> (OrganizationComponent organizationComponent : organizationComponents) &#123;<br>			organizationComponent.print();<br>		&#125;<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//University 就是 Composite , 可以管理College</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">University</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">OrganizationComponent</span> </span>&#123;<br><br>	List&lt;OrganizationComponent&gt; organizationComponents = <span class="hljs-keyword">new</span> ArrayList&lt;OrganizationComponent&gt;();<br><br>	<span class="hljs-comment">// 构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">University</span><span class="hljs-params">(String name, String des)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(name, des);<br>	&#125;<br><br>	<span class="hljs-comment">// 重写add</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(OrganizationComponent organizationComponent)</span> </span>&#123;<br>		organizationComponents.add(organizationComponent);<br>	&#125;<br><br>	<span class="hljs-comment">// 重写remove</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">remove</span><span class="hljs-params">(OrganizationComponent organizationComponent)</span> </span>&#123;<br>		organizationComponents.remove(organizationComponent);<br>	&#125;<br><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getName();<br>	&#125;<br><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDes</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getDes();<br>	&#125;<br><br>	<span class="hljs-comment">// print方法，就是输出University 包含的学院</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;--------------&quot;</span> + getName() + <span class="hljs-string">&quot;--------------&quot;</span>);<br>		<span class="hljs-comment">//遍历 organizationComponents </span><br>		<span class="hljs-keyword">for</span> (OrganizationComponent organizationComponent : organizationComponents) &#123;<br>			organizationComponent.print();<br>		&#125;<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//Department</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Department</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">OrganizationComponent</span> </span>&#123;<br><br>	<span class="hljs-comment">//没有集合</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Department</span><span class="hljs-params">(String name, String des)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>(name, des);<br>	&#125;<br>	<span class="hljs-comment">//add , remove 就不用写了，因为他是叶子节点</span><br>	<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getName();<br>	&#125;<br>	<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDes</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.getDes();<br>	&#125;<br>	<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(getName());<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//Client实现</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		<span class="hljs-comment">//从大到小创建对象 学校</span><br>		OrganizationComponent university = <span class="hljs-keyword">new</span> University(<span class="hljs-string">&quot;清华大学&quot;</span>, <span class="hljs-string">&quot; 中国顶级大学 &quot;</span>);<br>		<br>		<span class="hljs-comment">//创建 学院</span><br>		OrganizationComponent computerCollege = <span class="hljs-keyword">new</span> College(<span class="hljs-string">&quot;计算机学院&quot;</span>, <span class="hljs-string">&quot; 计算机学院 &quot;</span>);<br>		OrganizationComponent infoEngineercollege = <span class="hljs-keyword">new</span> College(<span class="hljs-string">&quot;信息工程学院&quot;</span>, <span class="hljs-string">&quot; 信息工程学院 &quot;</span>);<br>		<br>		<span class="hljs-comment">//创建各个学院下面的系(专业)</span><br>		computerCollege.add(<span class="hljs-keyword">new</span> Department(<span class="hljs-string">&quot;软件工程&quot;</span>, <span class="hljs-string">&quot; 软件工程不错 &quot;</span>));<br>		computerCollege.add(<span class="hljs-keyword">new</span> Department(<span class="hljs-string">&quot;网络工程&quot;</span>, <span class="hljs-string">&quot; 网络工程不错 &quot;</span>));<br>		computerCollege.add(<span class="hljs-keyword">new</span> Department(<span class="hljs-string">&quot;计算机科学与技术&quot;</span>, <span class="hljs-string">&quot; 计算机科学与技术是老牌的专业 &quot;</span>));<br>		<br>		<span class="hljs-comment">//</span><br>		infoEngineercollege.add(<span class="hljs-keyword">new</span> Department(<span class="hljs-string">&quot;通信工程&quot;</span>, <span class="hljs-string">&quot; 通信工程不好学 &quot;</span>));<br>		infoEngineercollege.add(<span class="hljs-keyword">new</span> Department(<span class="hljs-string">&quot;信息工程&quot;</span>, <span class="hljs-string">&quot; 信息工程好学 &quot;</span>));<br>		<br>		<span class="hljs-comment">//将学院加入到 学校</span><br>		university.add(computerCollege);<br>		university.add(infoEngineercollege);<br>		<br>		<span class="hljs-comment">//university.print();</span><br>		infoEngineercollege.print();<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>注意事项：</p>
<p>注意事项和细节</p>
<ol>
<li>简化客户端操作，客户端只需要面对一致的对象而不用考虑整体部分或者叶子结点的问题。</li>
<li>具有较强的扩展性，当我们要更改组合对象时，我们只需要调整内部的层次关系，客户端不用做出任何改动。</li>
<li>方便创建出复杂的层次结构。客户端不用理会组合里面的组成细节，容易添加结点或者叶子从而创建出复杂的树形结构</li>
<li>需要便利组织结构，或者处理的对象具有树形结构时，非常适合使用组合模式</li>
<li>要求较高的抽象性， 如果结点和叶子具有很多差异性的话，比如很多方法和属性都不一样，不适合用组合模式</li>
</ol>
<h3 id="外观模式"><a href="#外观模式" class="headerlink" title="外观模式"></a>外观模式</h3><h4 id="基本介绍-4"><a href="#基本介绍-4" class="headerlink" title="基本介绍"></a>基本介绍</h4><ul>
<li>外观模式(Facade)，也叫“过程模式” : 外观模式为子系统的一组接口提供一个一致的界面，此模式定义了一个高层接口，这个接口使得这一子系统更加容易使用</li>
<li>外观模式通过定义一个一致的接口，用以屏蔽内部子系统的细节，使得调用端只需跟这个接口发生调用，而无需关系这个子系统的内部细节</li>
</ul>
<p>原理类图说明(外观模式的角色)</p>
<ol>
<li>外观类(Facade):为调用端提供统一的调用接口，外观类知道哪些子类系统负责处理请求，从而将调用端的请求代理给适当的子系统对象</li>
<li>调用者(Client):外观接口的调用者</li>
<li>子系统的集合:指模块或者子系统，处理Facade对象指派的任务，他是功能的提供者</li>
</ol>
<p>外观模式就是解决多个复杂接口带来的使用困难，起到简化用户使用的作用。</p>
<h4 id="源码分析-3"><a href="#源码分析-3" class="headerlink" title="源码分析"></a>源码分析</h4><blockquote>
<p><code>Mybatis</code>中的configuration中使用了外观模式，</p>
<p>用户只需要传递一个Object，调用<code>metaObject</code>方法，而<code>getMetaObeject</code>方法中则组合了一系列<code>ObjectFactory</code>,一次判断返回的实例。相当于简化了用户的操作，在内部实现了一系列逻辑、</p>
<p>当我们调用子系统变得很困难的时候，以更高一层的接口来调用子系统，来提高系统使用和复用。</p>
</blockquote>
<p>外观模式的注意事项和细节</p>
<ol>
<li>外观模式对外屏蔽了子系统的细节，因此外观模式降低了客户端对子系统使用的复杂性</li>
<li>外观模式对客户端与子系统的耦合关系，让子系统内部的模块更易维护和扩展</li>
<li>通过合理使用外观模式，可以帮助我们更好的划分访问的层次</li>
<li>当系统需要进行分层设计时，可以考虑使用Facade模式</li>
<li>在维护一个遗留的大型系统时，可能这个系统已经变得非常难以维护和扩展，此时可以考虑为新系统开发一个Facade类，来提供遗留系统的比较清晰简单的接口，让新系统与Facade类交互，提高复用性</li>
<li>不能过多的或者不合理的使用外观模式，使用外观模式好还是直接调用模块好。要以让系统有层次，利于维护为目的。</li>
</ol>
<h3 id="享元模式"><a href="#享元模式" class="headerlink" title="享元模式"></a>享元模式</h3><h4 id="案例分析-2"><a href="#案例分析-2" class="headerlink" title="案例分析"></a>案例分析</h4><p>小型的外包项目，给客户A做一个产品展示网站，客户A的朋友感觉效果不错，也希望做这样的产品展示网站，但是要求都有些不同:</p>
<ul>
<li>有客户要求以新闻的形式发布</li>
<li>有客户人要求以博客的形式发布</li>
<li>有客户希望以微信公众号的形式发布</li>
</ul>
<blockquote>
<p>1)需要的网站结构相似度很高，而且都不是高访问量网站，如果分成多个虚拟空间来处理,<br>相当于一个相同网站<br>的实例对象很多，造成服务器的资源浪费<br>2)解决思路:整合到一个网站中，共享其相关的代码和数据，对于硬盘、内存、CPU、数据库空间等服务器资源<br>都可以达成共享，减少服务器资源<br>3)对于代码来说，由于是一份实例，维护和扩展都更加容易<br>4)上面的解决思路就可以使用享元模式来解决</p>
</blockquote>
<h4 id="基本介绍-5"><a href="#基本介绍-5" class="headerlink" title="基本介绍"></a>基本介绍</h4><ol>
<li><p>享元模式(Flyweight Pattern)也叫蝇量模式:运用共享技术有效地支持大量细粒度的对象</p>
</li>
<li><p>常用于系统底层开发，解决系统的性能问题。像数据库连接池，里面都是创建好的连接对象，在这些连接对象中有我们需要的则直接拿来用，避免重新创建，如果没有我们需要的，则创建一个</p>
</li>
<li><p>享元模式能够解决重复对象的内存浪费的问题，当系统中有大量相似对象，需要缓冲池时。不需总是创建新对象，可以从缓冲池里拿。这样可以降低系统内存，同时提高效率</p>
</li>
<li><p>享元模式经典的应用场景就是池技术了，String常量池、数据库连接池、缓冲池等等都是享元模式的应用，享元模式是池技术的重要实现方式</p>
</li>
</ol>
<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/xiangyuan.jpg" srcset="/img/loading.gif" lazyload alt="java"></p>
<blockquote>
<p>对类图的说明<br>对原理图的说明-即(模式的角色及职责)</p>
<ol>
<li><code>FlyWeight</code>是抽象的享元角色，他是产品的抽象类,同时定义出对象的外部状态和内部状态(后面介绍)的接口或实现</li>
<li><code>ConcreteFlyWeight</code>是具体的享元角色，是具体的产品类，实现抽象角色定义相关业务</li>
<li><code>UnSharedConcreteFlyWeight</code>是不可共享的角色，一般不会出现在享元工厂。</li>
<li><code>FlyWeightFactory</code>享元工厂类，用于构建一个池容器(集合)，同时提供从池中获取对象方法</li>
</ol>
</blockquote>
<p>类似线程池，享元共享的数据是不可变的，可以共享资源。如果没有就创建，有就直接拿来用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//用户</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>&#123; <br>	<span class="hljs-keyword">private</span> String name;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(String name)</span> </span>&#123;<br>		<span class="hljs-keyword">super</span>();<br>		<span class="hljs-keyword">this</span>.name = name;<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> name;<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>&#123;<br>		<span class="hljs-keyword">this</span>.name = name;<br>	&#125;<br>&#125;<br><span class="hljs-comment">//网站的抽象类</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebSite</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">(User user)</span></span>;<span class="hljs-comment">//抽象方法</span><br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 网站工厂类，根据需要返回压一个网站</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebSiteFactory</span> </span>&#123;<br><br>	<span class="hljs-comment">//集合， 充当池的作用</span><br>	<span class="hljs-keyword">private</span> HashMap&lt;String, ConcreteWebSite&gt; pool = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();<br>	<br>	<span class="hljs-comment">//根据网站的类型，返回一个网站, 如果没有就创建一个网站，并放入到池中,并返回</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> WebSite <span class="hljs-title">getWebSiteCategory</span><span class="hljs-params">(String type)</span> </span>&#123;<br>		<span class="hljs-keyword">if</span>(!pool.containsKey(type)) &#123;<br>			<span class="hljs-comment">//就创建一个网站，并放入到池中</span><br>			pool.put(type, <span class="hljs-keyword">new</span> ConcreteWebSite(type));<br>		&#125;<br>		<br>		<span class="hljs-keyword">return</span> (WebSite)pool.get(type);<br>	&#125;<br>	<br>	<span class="hljs-comment">//获取网站分类的总数 (池中有多少个网站类型)</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getWebSiteCount</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> pool.size();<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//具体网站</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteWebSite</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WebSite</span> </span>&#123;<br>	<span class="hljs-comment">//共享的部分，内部状态</span><br>	<span class="hljs-keyword">private</span> String type = <span class="hljs-string">&quot;&quot;</span>; <span class="hljs-comment">//网站发布的形式(类型)</span><br>	<span class="hljs-comment">//构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ConcreteWebSite</span><span class="hljs-params">(String type)</span> </span>&#123;<br>		<br>		<span class="hljs-keyword">this</span>.type = type;<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">(User user)</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;网站的发布形式为:&quot;</span> + type + <span class="hljs-string">&quot; 在使用中 .. 使用者是&quot;</span> + user.getName());<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//Client 客户端</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		<span class="hljs-comment">// 创建一个工厂类</span><br>		WebSiteFactory factory = <span class="hljs-keyword">new</span> WebSiteFactory();<br>		<span class="hljs-comment">// 客户要一个以新闻形式发布的网站</span><br>		WebSite webSite1 = factory.getWebSiteCategory(<span class="hljs-string">&quot;新闻&quot;</span>);<br>		<br>		webSite1.use(<span class="hljs-keyword">new</span> User(<span class="hljs-string">&quot;tom&quot;</span>));<br>		<span class="hljs-comment">// 客户要一个以博客形式发布的网站</span><br>		WebSite webSite2 = factory.getWebSiteCategory(<span class="hljs-string">&quot;博客&quot;</span>);<br>		webSite2.use(<span class="hljs-keyword">new</span> User(<span class="hljs-string">&quot;jack&quot;</span>));<br>		<span class="hljs-comment">// 客户要一个以博客形式发布的网站</span><br>		WebSite webSite3 = factory.getWebSiteCategory(<span class="hljs-string">&quot;博客&quot;</span>);<br>		webSite3.use(<span class="hljs-keyword">new</span> User(<span class="hljs-string">&quot;smith&quot;</span>));<br><br>		<span class="hljs-comment">// 客户要一个以博客形式发布的网站</span><br>		WebSite webSite4 = factory.getWebSiteCategory(<span class="hljs-string">&quot;博客&quot;</span>);<br>		webSite4.use(<span class="hljs-keyword">new</span> User(<span class="hljs-string">&quot;king&quot;</span>));<br>		System.out.println(<span class="hljs-string">&quot;网站的分类共=&quot;</span> + factory.getWebSiteCount());<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h4 id="源码分析-4"><a href="#源码分析-4" class="headerlink" title="源码分析"></a>源码分析</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FlyWeight</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		<span class="hljs-comment">//如果 Integer.valueOf(x) x 在  -128 --- 127 直接，就是使用享元模式返回,如果不在</span><br>		<span class="hljs-comment">//范围类，则仍然 new </span><br>		<span class="hljs-comment">//小结:</span><br>		<span class="hljs-comment">//1. 在valueOf 方法中，先判断值是否在 IntegerCache 中，</span><br>         <span class="hljs-comment">//如果不在，就创建新的Integer(new), 否则，就直接从 缓存池返回</span><br>		<span class="hljs-comment">//2. valueOf 方法，就使用到享元模式</span><br>		<span class="hljs-comment">//3. 如果使用valueOf 方法得到一个Integer 实例，范围在 -128 - 127 ，执行速度比 new 快</span><br><br>		Integer x = Integer.valueOf(<span class="hljs-number">127</span>); <span class="hljs-comment">// 得到 x实例，类型 Integer</span><br>		Integer y = <span class="hljs-keyword">new</span> Integer(<span class="hljs-number">127</span>); <span class="hljs-comment">// 得到 y 实例，类型 Integer</span><br>		Integer z = Integer.valueOf(<span class="hljs-number">127</span>);<span class="hljs-comment">//..</span><br>		Integer w = <span class="hljs-keyword">new</span> Integer(<span class="hljs-number">127</span>);<br>		<br>		System.out.println(x.equals(y)); <span class="hljs-comment">// 大小，true</span><br>		System.out.println(x == y ); <span class="hljs-comment">//  false</span><br>		System.out.println(x == z ); <span class="hljs-comment">// true</span><br>		System.out.println(w == x ); <span class="hljs-comment">// false</span><br>		System.out.println(w == y ); <span class="hljs-comment">// false</span><br>		<br>		Integer x1 = Integer.valueOf(<span class="hljs-number">200</span>);<br>		Integer x2 = Integer.valueOf(<span class="hljs-number">200</span>);<br>		System.out.println(<span class="hljs-string">&quot;x1==x2&quot;</span> + (x1 == x2)); <span class="hljs-comment">// false</span><br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="小结："><a href="#小结：" class="headerlink" title="小结："></a>小结：</h4><ol>
<li>享元模式中的享可以理解为共享，元理解为对象，就是共享对象模式。比如共享连接池</li>
<li>系统中有大量对象，这些对象消耗大量内存，并且对象的状态大部分可以外部化时，我们就可以考虑选用享元模式</li>
<li>用唯一标识码判断，如果内存中有，则返回这个唯一标识码所标识的对象，用<code>HashMap/HashTable</code>存储</li>
<li>享元模式大大的减少了对象的创建，降低了程序内存的占用，提高效率。</li>
<li>享元模式提高了系统的复杂度，因为需要分离出内部状态和外部状态，而外部状态具有固化特性，不应该随着内部状态的改变而改变，这点在使用享元模式需要注意。</li>
<li>使用享元模式时，注意划分内部状态和外部状态，并且需要有一个工厂类加以控制，</li>
<li>享元模式经典的应用场景是需要缓冲池，比如String常量池，数据库连接池，以及围棋观赛黑白子对象。</li>
</ol>
<h2 id="行为型模式"><a href="#行为型模式" class="headerlink" title="行为型模式"></a>行为型模式</h2><h3 id="模板模式"><a href="#模板模式" class="headerlink" title="模板模式"></a>模板模式</h3><h4 id="案例分析-3"><a href="#案例分析-3" class="headerlink" title="案例分析"></a>案例分析</h4><p>制作豆浆</p>
<h4 id="基本介绍-6"><a href="#基本介绍-6" class="headerlink" title="基本介绍"></a>基本介绍</h4><ol>
<li>模板方法模式(Template  Method Pattern) ,在一个抽象类公开了执行它的方法的模板。它的子类可以按需重写方法实现，但调用将以抽象类中定义的方法执行。</li>
<li>简单说模板方法模式定义一个操作中的算法骨架，而将一些步骤延迟到子类中，使得子类可以不改变一个算法的结构就可以重定义该算法的某些步骤。</li>
</ol>
<p>原理类图说明</p>
<ul>
<li><code>AbstractClass</code> 抽象类，类中实现了模板方法，定义了算法的骨架，具体子类需要去实现 其他的抽象方法</li>
<li><code>ConcreateClass</code> 实现抽象方法，已完成算法中特点子类的步骤</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//抽象类，表示豆浆</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SoyaMilk</span> </span>&#123;<br><br>	<span class="hljs-comment">//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.</span><br>	<span class="hljs-function"><span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">make</span><span class="hljs-params">()</span> </span>&#123;<br>		select(); <br>		<span class="hljs-keyword">if</span>(customerWantCondiments()) &#123; <span class="hljs-comment">//判断是实现默认方法还是子类重写的方法</span><br>			addCondiments();<br>		&#125;<br>		soak();<br>		beat();<br>	&#125;<br>	<br>	<span class="hljs-comment">//选材料</span><br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">select</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;第一步：选择好的新鲜黄豆  &quot;</span>);<br>	&#125;<br>	<br>	<span class="hljs-comment">//添加不同的配料， 抽象方法, 子类具体实现</span><br>	<span class="hljs-function"><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addCondiments</span><span class="hljs-params">()</span></span>;<br>	<br>	<span class="hljs-comment">//浸泡</span><br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">soak</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;第三步， 黄豆和配料开始浸泡， 需要3小时 &quot;</span>);<br>	&#125;<br>	 <br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">beat</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;第四步：黄豆和配料放到豆浆机去打碎  &quot;</span>);<br>	&#125;<br>	<br>	<span class="hljs-comment">//钩子方法，决定是否需要添加配料</span><br>	<span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">customerWantCondiments</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;<br>	&#125;<br>&#125;<br><br><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RedBeanSoyaMilk</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SoyaMilk</span> </span>&#123;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">addCondiments</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 加入上好的红豆 &quot;</span>);<br>	&#125;<br>&#125;<br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PureSoyaMilk</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SoyaMilk</span> </span>&#123;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">addCondiments</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">//空实现</span><br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">customerWantCondiments</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;<br>	&#125;<br>&#125;<br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PeanutSoyaMilk</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SoyaMilk</span> </span>&#123;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">addCondiments</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 加入上好的花生 &quot;</span>);<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot;----制作红豆豆浆----&quot;</span>);<br>		SoyaMilk redBeanSoyaMilk = <span class="hljs-keyword">new</span> RedBeanSoyaMilk();<br>		redBeanSoyaMilk.make();<br>		<br>		System.out.println(<span class="hljs-string">&quot;----制作花生豆浆----&quot;</span>);<br>		SoyaMilk peanutSoyaMilk = <span class="hljs-keyword">new</span> PeanutSoyaMilk();<br>		peanutSoyaMilk.make();<br>		<br>		System.out.println(<span class="hljs-string">&quot;----制作纯豆浆----&quot;</span>);<br>		SoyaMilk pureSoyaMilk = <span class="hljs-keyword">new</span> PureSoyaMilk();<br>		pureSoyaMilk.make();<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>在模板方法中添加一个钩子方法默认不做事，子类就可以根据狗子方法来决定是否覆盖这个方法。</p>
<p>这样就可以默认实现了</p>
<h4 id="源码分析-5"><a href="#源码分析-5" class="headerlink" title="源码分析"></a>源码分析</h4><blockquote>
<p>Spring中 <code>IOC</code>容器初始化的时候 使用了模板模式</p>
</blockquote>
<h4 id="小结：-1"><a href="#小结：-1" class="headerlink" title="小结："></a>小结：</h4><ol>
<li>基本思想是，算法只存在于一个地方，也就是在父类中，容易修改。修改算法时，只需要修改父类方法或者已经实现的某些步骤，子类就会继承这些修改。</li>
<li>实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。</li>
<li>即统一了算法，也提供了很大的灵活性，父类的模板方法确保了算法结构保持不变，同时由子类提供部分步骤的实现。</li>
<li>该模式不足之处是 每一个不同的实现都需要一个子类实现，容易导致类的个数增加导致系统庞大</li>
<li>一般方法都加上关键字final，防止子类重写模板方法</li>
<li>模板方法使用场景：当要完成在某个过程，该过程要执行一系列步骤，这一系列的步骤基本相同，单个别步骤在实现的时候可能不同，通常考虑用模板方法来处理。</li>
</ol>
<h3 id="命令模式"><a href="#命令模式" class="headerlink" title="命令模式"></a>命令模式</h3><h4 id="案例需求"><a href="#案例需求" class="headerlink" title="案例需求"></a>案例需求</h4><p>1)我们买了一套智能家电，有照明灯、风扇、冰箱、洗衣机，我们只要在手机上安装 <code>app</code>就可以控制对这些家电<br>工作。<br>2)这些智能家电来自不同的厂家，我们不想针对每一种家电都安装一个<code>App</code>，分别控制，我们希望只要一个<code>app</code><br>就可以控制全部智能家电。<br>3)要实现一个<code>app</code>控制所有智能家电的需要，则每个智能家电厂家都要提供一个统一的接口给app调用，这时就<br>可以考虑使用命令模式。<br>4)命令模式可将“动作的请求者”从“动作的执行者”对象中解耦出来.<br>5)在我们的例子中，动作的请求者是手机 <code>app</code>，动作的执行者是每个厂商的一个家电产品</p>
<h4 id="基本介绍-7"><a href="#基本介绍-7" class="headerlink" title="基本介绍"></a>基本介绍</h4><ul>
<li>命令模式(Command Pattern):在软件设计中，我们经常需要向某些对象发送请求，但是并不知道请求的接收<br>者是谁，也不知道被请求的操作是哪个，<br>我们只需在程序运行时指定具体的请求接收者即可，此时，可以使用命令模式来进行设计</li>
<li>命名模式使得请求发送者与请求接收者消除彼此之间的耦合，让对象之间的调用关系更加灵活，实现解耦。</li>
<li>在命名模式中，会将一个请求封装为一个对象，以便使用不同参数来表示不同的请求(即命名)，同时命令模式<br>也支持可撤销的操作。</li>
<li>通俗易懂的理解:将军发布命令，士兵去执行。其中有几个角色:将军(命令发布者)、士兵(命令的具体执<br>行者)、命令(连接将军和士兵)。<br><code>lInvoker</code>是调用者（将军)，Receiver是被调用者（士兵)，<code>MyCommand</code>是命令，实现了Command接口，持有接收对象</li>
</ul>
<h4 id="原理类图分析"><a href="#原理类图分析" class="headerlink" title="原理类图分析"></a>原理类图分析</h4><h4 id="代码实现-1"><a href="#代码实现-1" class="headerlink" title="代码实现"></a>代码实现</h4><p>类图分析：</p>
<p><img src="http://www.slx.blue/2021/12/03/javaDesignMode/command.png" srcset="/img/loading.gif" lazyload alt="java"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//创建命令接口</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Command</span> </span>&#123;<br>	<span class="hljs-comment">//执行动作(操作)</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span>;<br>	<span class="hljs-comment">//撤销动作(操作)</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">undo</span><span class="hljs-params">()</span></span>;<br>&#125;<br><br><span class="hljs-comment">//关灯命令</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LightOffCommand</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Command</span> </span>&#123;<br>	<span class="hljs-comment">// 聚合LightReceiver</span><br>	LightReceiver light;<br><br>	<span class="hljs-comment">// 构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">LightOffCommand</span><span class="hljs-params">(LightReceiver light)</span> </span>&#123;<br>			<span class="hljs-keyword">this</span>.light = light;<br>		&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">// 调用接收者的方法</span><br>		light.off();<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">undo</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">// 调用接收者的方法</span><br>		light.on();<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//开灯命令</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LightOnCommand</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Command</span> </span>&#123;<br>	<span class="hljs-comment">//聚合LightReceiver</span><br>	LightReceiver light;<br>	<br>	<span class="hljs-comment">//构造器</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">LightOnCommand</span><span class="hljs-params">(LightReceiver light)</span> </span>&#123;<br>		<span class="hljs-keyword">this</span>.light = light;<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">//调用接收者的方法</span><br>		light.on();<br>	&#125;<br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">undo</span><span class="hljs-params">()</span> </span>&#123;<br>		<span class="hljs-comment">//调用接收者的方法</span><br>		light.off();<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 没有任何命令，即空执行: 用于初始化每个按钮, 当调用空命令时，对象什么都不做</span><br><span class="hljs-comment"> * 其实，这样是一种设计模式, 可以省掉对空判断</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> Administrator</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NoCommand</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Command</span> </span>&#123;<br>	<span class="hljs-comment">//只需要实现两个空方法 钩子</span><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> </span>&#123;<br>	&#125;<br><br>	<span class="hljs-meta">@Override</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">undo</span><span class="hljs-params">()</span> </span>&#123;<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//任务接收者 执行者</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LightReceiver</span> </span>&#123;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">on</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 电灯打开了.. &quot;</span>);<br>	&#125;<br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">off</span><span class="hljs-params">()</span> </span>&#123;<br>		System.out.println(<span class="hljs-string">&quot; 电灯关闭了.. &quot;</span>);<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//控制器 遥控器 Invoker 任务发布者</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RemoteController</span> </span>&#123;<br><br>	<span class="hljs-comment">// 开 按钮的命令数组</span><br>	Command[] onCommands;<br>	Command[] offCommands;<br><br>	<span class="hljs-comment">// 执行撤销的命令</span><br>	Command undoCommand;<br><br>	<span class="hljs-comment">// 构造器，完成对按钮初始化</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">RemoteController</span><span class="hljs-params">()</span> </span>&#123;<br>		onCommands = <span class="hljs-keyword">new</span> Command[<span class="hljs-number">5</span>];<br>		offCommands = <span class="hljs-keyword">new</span> Command[<span class="hljs-number">5</span>];<br><br>		<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; i++) &#123;<br>			onCommands[i] = <span class="hljs-keyword">new</span> NoCommand();<br>			offCommands[i] = <span class="hljs-keyword">new</span> NoCommand();<br>		&#125;<br>	&#125;<br><br>	<span class="hljs-comment">// 给我们的按钮设置你需要的命令</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setCommand</span><span class="hljs-params">(<span class="hljs-keyword">int</span> no, Command onCommand, Command offCommand)</span> </span>&#123;<br>		onCommands[no] = onCommand;<br>		offCommands[no] = offCommand;<br>	&#125;<br><br>	<span class="hljs-comment">// 按下开按钮</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onButtonWasPushed</span><span class="hljs-params">(<span class="hljs-keyword">int</span> no)</span> </span>&#123; <span class="hljs-comment">// no 0</span><br>		<span class="hljs-comment">// 找到你按下的开的按钮， 并调用对应方法</span><br>		onCommands[no].execute();<br>		<span class="hljs-comment">// 记录这次的操作，用于撤销</span><br>		undoCommand = onCommands[no];<br><br>	&#125;<br><br>	<span class="hljs-comment">// 按下开按钮</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">offButtonWasPushed</span><span class="hljs-params">(<span class="hljs-keyword">int</span> no)</span> </span>&#123; <span class="hljs-comment">// no 0</span><br>		<span class="hljs-comment">// 找到你按下的关的按钮， 并调用对应方法</span><br>		offCommands[no].execute();<br>		<span class="hljs-comment">// 记录这次的操作，用于撤销</span><br>		undoCommand = offCommands[no];<br><br>	&#125;<br>	<br>	<span class="hljs-comment">// 按下撤销按钮</span><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">undoButtonWasPushed</span><span class="hljs-params">()</span> </span>&#123;<br>		undoCommand.undo();<br>	&#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//Client客户端</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>&#123;<br><br>	<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>		<span class="hljs-comment">//使用命令设计模式，完成通过遥控器，对电灯的操作</span><br>		<span class="hljs-comment">//创建电灯的对象(接受者)</span><br>		LightReceiver lightReceiver = <span class="hljs-keyword">new</span> LightReceiver();<br>		<br>		<span class="hljs-comment">//创建电灯相关的开关命令</span><br>		LightOnCommand lightOnCommand = <span class="hljs-keyword">new</span> LightOnCommand(lightReceiver);<br>		LightOffCommand lightOffCommand = <span class="hljs-keyword">new</span> LightOffCommand(lightReceiver);<br>		<br>		<span class="hljs-comment">//需要一个遥控器</span><br>		RemoteController remoteController = <span class="hljs-keyword">new</span> RemoteController();<br>		<br>		<span class="hljs-comment">//给我们的遥控器设置命令, 比如 no = 0 是电灯的开和关的操作</span><br>		remoteController.setCommand(<span class="hljs-number">0</span>, lightOnCommand, lightOffCommand);<br>		<br>		System.out.println(<span class="hljs-string">&quot;--------按下灯的开按钮-----------&quot;</span>);<br>		remoteController.onButtonWasPushed(<span class="hljs-number">0</span>);<br>		System.out.println(<span class="hljs-string">&quot;--------按下灯的关按钮-----------&quot;</span>);<br>		remoteController.offButtonWasPushed(<span class="hljs-number">0</span>);<br>		System.out.println(<span class="hljs-string">&quot;--------按下撤销按钮-----------&quot;</span>);<br>		remoteController.undoButtonWasPushed();<br>		<br><br>		<span class="hljs-comment">//如果后期需要扩展新的命令 就非常容易扩展 不需要修改Controller的内容 符合开闭原则</span><br>		<span class="hljs-comment">/*</span><br><span class="hljs-comment">		System.out.println(&quot;=========使用遥控器操作电视机==========&quot;);</span><br><span class="hljs-comment">		TVReceiver tvReceiver = new TVReceiver();</span><br><span class="hljs-comment">		TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);</span><br><span class="hljs-comment">		TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);</span><br><span class="hljs-comment">		//给我们的遥控器设置命令, 比如 no = 1 是电视机的开和关的操作</span><br><span class="hljs-comment">		remoteController.setCommand(1, tvOnCommand, tvOffCommand);</span><br><span class="hljs-comment">		</span><br><span class="hljs-comment">		System.out.println(&quot;--------按下电视机的开按钮-----------&quot;);</span><br><span class="hljs-comment">		remoteController.onButtonWasPushed(1);</span><br><span class="hljs-comment">		System.out.println(&quot;--------按下电视机的关按钮-----------&quot;);</span><br><span class="hljs-comment">		remoteController.offButtonWasPushed(1);</span><br><span class="hljs-comment">		System.out.println(&quot;--------按下撤销按钮-----------&quot;);</span><br><span class="hljs-comment">		remoteController.undoButtonWasPushed();</span><br><span class="hljs-comment">		*/</span><br><br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="源码分析-6"><a href="#源码分析-6" class="headerlink" title="源码分析"></a>源码分析</h4><blockquote>
<p>Spring中的JDBCTemplate中使用了模板模式</p>
</blockquote>
<h4 id="小结-3"><a href="#小结-3" class="headerlink" title="小结"></a>小结</h4><blockquote>
<p>注意事项和细节</p>
</blockquote>
<ol>
<li>将发起请求的对象与执行请求的对象解耦。发起请求的对象是调用者，调用者只要调用命令对象的execute()方法就可以让接收着工作，而不必知道记得接收着对象谁，如何实现的，命令对象会负责让接受者执行请求的动作，也就是“请求发起者”和“请求执行者”之间的解耦是通过命令对象实现的，命令对象起到了扭到桥梁的作用。</li>
<li>容易设计一个命令队列，只要把命令对象放到队列，就可以实现多线程的命令</li>
<li>容易实现对请求的撤销和重做</li>
<li>命令模式的不足：可能导致某些系统有过多的具体命令类，增加了系统的复杂度，这点在使用的时候要注意</li>
<li>空命令也是一种设计模式，它为我们省去了判空的操作，在上面的案例，如果没有用空命令，那么每一个按键我们都要做判空操作，对编码带来了一定的麻烦。</li>
<li>命令模式经典的应用场景：界面的一个按钮都是一条命令，模拟CMD（DOS）命令，订单的撤销/恢复、触发反馈机制</li>
</ol>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/designMode/">designMode</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/">设计模式</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客目前大部分文章都是参考尚硅谷或者马士兵教育的学习资料！<a href="http://www.atguigu.com/" rel="nofollow noopener"官网地址！</a> 
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/12/03/mybatis04/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">mybatis-缓存</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                

              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">

  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
	<!--《添加网站运行时间 -->
<br/>

<span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
<script>
var now = new Date(); 

function createtime() {
    //此处修改你的建站时间或者网站上线时间
    var grt = new Date('11/02/2021 21:39:00');
    now.setTime(now.getTime() + 250);
    days = (now - grt) / 1000 / 60 / 60 / 24;

    dnum = Math.floor(days);
    hours = (now - grt) / 1000 / 60 / 60 - (24 * dnum);
    hnum = Math.floor(hours);
    if (String(hnum).length == 1) {
        hnum = "0" + hnum;
    }
    minutes = (now - grt) / 1000 / 60 - (24 * 60 * dnum) - (60 * hnum);
    mnum = Math.floor(minutes);
    if (String(mnum).length == 1) {
        mnum = "0" + mnum;
    }
    seconds = (now - grt) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
    snum = Math.round(seconds);
    if (String(snum).length == 1) {
        snum = "0" + snum;
    }
    document.getElementById("timeDate").innerHTML = " 本站已各种夹缝中安全运行 " + dnum + " 天 ";
    document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()", 250);
</script>

<!-- 添加网站运行时间》-->
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
